版本修订

版本 作者 时间 描述

1.00

虞浪

2023-02-07

起草基本云平台规范

1.01

虞浪

2023-02-12

动态建模平台一键式部署修订

1.02

虞浪

2023-02-14

前端结构规范补充

1.03

虞浪

2023-02-22

前端样式规范补充

1.04

虞浪

2023-03-11

配置/实施规范中的权限管理

0. 环境标准

0.1.环境要求

0.1.1.后端开发

分类 版本 执行命令 用途

运行时

17+

java

下载,Java环境

运行时

3.2.0

ruby, gem

下载,推荐AsciiDoc使用Ruby方式安装

运行时

2.37.1+

git

下载,MacOS中XCode自带

运行时

6.5

tiup

下载,TiDB命令

0.1.2.前端开发

分类 版本 执行命令 用途

运行时

19.6+

node, npm

下载,NodeJS环境

构建

1.22.19

yarn

(npm)直接安装,前端主构建工具

构建

5.75.0

webpack

框架

5.2.0

-

Ant Design主界面库

框架

2.3.54

-

Ant Design Pro企业框架主库

框架

4.2.9

-

Ant G2图表库

框架

2.3.0

-

Ant G6拓扑图、树图、脑图库

框架

11.3.1

-

BPMN工作流前端专用库

框架

18.2.0

-

React主框架库

框架

6.8.1

-

React-Router专用库

框架

16.0.1

-

React Dnd拖拽主库

0.1.3.运维部署

分类 版本 执行命令 用途

构建

3.8.x+

mvn

下载,Maven环境

构建

1.0.0-m4

mvnd

下载,并行Maven环境(自带Maven 4.0)

构建

7.6+

gradle

下载,Gradle环境

容器:运行时

20.x

docker, docker-compose

下载,容器运行时,新版自带K8S单节点集群环境

容器:镜像工具

1.8.5

packer

下载,镜像工具,Maven可使用插件直接打包镜像

自动部署

2.14.2

ansible

下载,应用配置自动部署工具

自动部署

1.3.7

terraform

下载,基础设施自动部署工具

0.1.4.文档管理

分类 版本 执行命令 用途

文档

4.0.x

jsdoc

(npm/yarn)JavaScript文档生成

文档

1.2.2

live-server

(npm/yarn)文档服务器

文档

-

dash

(npm/yarn)标准文档皮肤工具

文档

2.0.18

asciidoctor

(gem)AsciiDoc文档生成工具

0.2.开发流程

0.2.1.流程图

开发流程走开源社区普遍的Fork流程,整体流程图如下:

Fork

整个环境中包括两种PR

  • Dev PR / develop分支:从开发人员Fork分支中直接提交PR到 develop 分支的PR,develop 分支可配置到测试环境中直接提供给测试人员测试。

  • Release PR / master分支:从 develop 分支提交同库PR到 master 分支中。

develop 分支和 master 分支追加保护功能,锁定之后不允许任何形式的 push 动作直接修改分支中的内容,仅走PR流程可更改两个分支中的代码。

0.2.2.操作步骤

操作流程参考如下步骤:

  1. 在远程环境创建Fork(手工操作),Fork之后拿到自己的分支代码路径(如:https://gitee.com/account/xc.git)

  2. 使用git命令从远程个人账号中下载代码

    $ git clone https://gitee.com/account/xc.git
  3. 在本机项目中运行命令添加远程引用(引用名推荐:upstream):

    $ git remote add upstream https://gitee.com/silentbalanceyh/xc.git
  4. (上述三步执行完成后就搭建好了本地代码整体环境)提交代码流程:

    $ git add .
    $ git commit -m "您的备注信息"
    # 该步骤会提交代码到您自己的Fork分支:https://gitee.com/account/xc.git
    $ git push
  5. 代码提交之后可在线提交PR到 develop 分支中,Code Review之后执行合并。

  6. 更新代码流程:

    # 注意更新代码是从upstream中更新(develop分支):https://gitee.com/silentbalanceyh/xc.git
    $ git pull upstream develop
    
    # 此步骤的目的是保持最新代码推送到自己Fork分支中
    $ git push

0.3.部署流程

0.3.1.流程图

部署流程参考下图:

Fork

0.3.2.关于IaC

IaC,全称为Infrastructure As Code(基础设施即代码),该术语在基础设施自动化时经常听到,它优势如下:

  1. 使用IaC,只需单击一下即可重新创建任何复杂的基础结构。

  2. 可以以IaC的形式对基础结构状态执行 版本控制

  3. 以开发人员为中心的基础架构管理工作流程,和开发的应用程序一样,IaaC代码的标准做法是遵循所有标准编码实践(测试、审查等)。

整个工作流中同时使用ansible和terraform是不冲突的,前者负责 配置管理(应用配置管理),后者负责 基础设施(服务器、网络、虚拟机、数据库等),协同工作,再借用Jenkins工具做好DevOps的流水线工作,实现最终开发、测试、生产环境的自动化开发测试运维部署。

1. 工程规范

1.1.后端结构规范

目录规范主要借鉴 Zero脚手架,该脚手架现阶段已运行过7个生产环境案例,这些案例均使用 Zero Framework 做后端开发主框架,配合工具箱 Cloud工具箱 可实现自动化环境,让开发人员集中精力处理 业务需求

举个例子,假设有一个项目如下(为了脱敏,此处为虚拟项目):

属性 说明

项目名

那由多轨迹平台

项目编码

nd,项目编码最好维持在三个或者两个字母

模块名称

commerce,模块名称可随意,脚手架中的模块名称只是实例用,您可以根据自己的方式设置(此处演示用,如果该应用只有一个模块,可直接使用nd代替,此处的命名规则遵循自定义和一定自由度。)

仓库地址

https://gitee.com/silentbalanceyh/nd.git

后端项目名

nd-api、nd或nd-micro,推荐:nd

前端项目名

nd-ui、或nd-web,推荐:nd-ui

1.1.1.根项目结构(nd)

Scaffold项目的整体目录结构如下:

Maven类型 主项目 说明

i pom pom

nd

当前应用主项目(根项目)

i jar jar

nd / nd-app

(入口)启动器

i jar pom

nd / nd-infix

插件集

i pom pom

nd / nd-inst

辅助工具指令集(Instruction),自动化工具包

i jar jar

nd / nd-inst / nd-dpma

数据处理工具(原Loader)

i pom pom

nd / nd-module

模块包,包含当前应用所需的所有模块(对应BLOCK)

i jar jar

nd / nd-module / nd-core

核心模块,主项目核心模块(包含了domain领域模型)

i pom pom

nd / nd-zone

底座集

i jar jar

nd / nd-zone / nd-zero

底座Zero框架连接,负责连接 zero-vie 或其他可连接点(实际依赖连接点)

命名规则实际是按照从上到下的模式搭建依赖关系,所以上述排序就是应用程序的依赖 结构,所以Scaffold项目的结构如下图:

脚手架

插件集没有位于图中,根据需要您可以放在任意位置运行)。通常一个小的应用或微服务模块仅提供一个 nd-commerce 就够用了,但在某些复杂的管理系统中,模块本身由单机演化而来,配合集成、插件、遗留升级等各种操作,具体架构方向是往上下两头拉开,形成下层(基础层 nd-down )和上层(业务层 nd-up ),这样的结构在目前案例中持续存在且证明是行之有效的。对整个系统的微架构而言,不推荐拆分太多层级模块,理论上 nd-module 中的所有模块都是平行的。上述结构只是脚手架中提供的基础结构,您也可以根据实际需要进行调整和修改,上述结构仅供参考。

Zero Framework中的所有根项目都是从 vertx-import 中导入的,参考下边的 pom.xml

    <parent>
        <artifactId>vertx-import</artifactId>
        <groupId>cn.vertxup</groupId>
        <version>0.9.0-SNAPSHOT</version>
    </parent>

父项目的核心执行命令文件

文件 说明

i cmd /build.bat

Windows平台编译命令

i bash /build.sh

Linux/Unix平台编译命令

i bash /build-inc.sh

「高级」带zero框架编译的编译命令,Windows可不考虑,只有zero框架修改时会用到

父项目还需要做以下几个事:

  1. 所有依赖库的版本管理(包含当前项目中的jar版本管理)。

  2. 共享依赖项的引入,此处只引入所有模块都需要使用的三方依赖项,若只是单独项目所需则在项目内部引入。

  3. License/作者/仓库版权等相关信息。

1.1.2.资源目录规范

资源目录规范属于Zero Extension部分的内容,主要应用于 启动器模块 两部分,后续讲解的启动器和模块部分是基于资源目录追加的新规范而已。本章节以目录规范为主体,只枚举特殊文件的功能,核心启动器文件规范放到启动器章节补充,同时参考下边的基本阅读规则:

  • <name> 表示动态建模模块名(非模型名称),如CMDB应用中:<name> = cmdb ,所以建模目录位于: /atom/cmdb/ 下。

  • 带 @ 标识的被认为是 Loader(包括新版中的 iac-load.jar )可识别的数据目录(默认只导入 init/oob ),只有该目录之下的内容会被加载,其他目录的所有Excel、Json都不视为数据文件,直接被忽略。

类型 路径 功能

i folder / i json 目录

action/

「zero-rbac」权限管理中 操作管理 配置目录。

i folder / i json 目录

authority/

「zero-rbac」权限管理中 授权管理 配置目录。

i folder / i json 目录

atom/<name>/reference/

「zero-atom」动态建模管理模型通道引用配置目录。

i folder / i json 目录

atom/<name>/rule/

「zero-atom」动态建模标识规则配置目录。

i folder / i msexcel 目录

atom/<name>/meta/

「zero-atom」动态建模数据源Excel文件配置目录。

i folder / i json 目录

cab/cn/

「zero-ambient」此处cn是平台运行语言(后端LANGUAGE字段,前端Z_LANGUAGE环境变量),cab目录和 Zero UI 中的资源目录cab实现无缝映射(前后端统一路径)——通常该处加载路径配置在 X_MODULE 表结构中。

i folder / i json 目录

cab/directory/

「zero-ambient/zero-is」文档管理模块专用目录结构树数据源配置。

i folder / i yaml 目录

codex/

「标准框架」后端验证器(Bean Validation)专用配置目录,增强型数据模型验证专用。

i folder / i bash 目录

environment/

Zero Shell Framework默认存储交互式命令行。

i folder / i json 目录

dict/<type>/

字典类型元数据部分的 metadata 配置,type对应字典中的 S_TYPE

i folder / i key 文件

keys/

「zero-rbac」证书专用目录。

i key 文件

keys/keystore.jceks

「zero-rbac」安全模块专用的证书文件。

i key 文件

keys/ipc/rpc-server-keystore.jks

「zero-rbac」RPC安全模块专用的证书文件。

i folder / i json 目录

hybrid/

「模型」静态模型。

i folder / i json 目录

hybrid/workflow/

「模型」工作流模型。

i folder / i msexcel 目录

init/integration/

「zero-jet」(调试专用)集成通道模拟器,模拟集成端可执行单元测试。

i folder / i msexcel 目录

init/job/

「zero-jet」(调试专用)任务配置器,通常用与任务专用配置。

i folder / i msexcel 目录

init/oob/cab/

@ / S_ACTION资源/操作配置数据目录。

i folder / i msexcel 目录

init/oob/data/

@ / OOB业务数据目录。

i folder / i node 目录

init/oob/menu/

@ / (新版)菜单规划路由数据目录。

i folder / i node 目录

init/oob/modulat/

@ / (新版)模块化数据目录(和菜单规划配合)。

i folder / i json 目录

init/oob/module/crud/

@ / 模块化内部CRUD模板化配置文件,调用 zero-crud

i folder / i json 目录

init/oob/module/ui/

@ / 单个模块界面列定义(静态模式)存储路径,动态模式调用 zero-ui

i folder / i msexcel 目录

init/oob/role/

@ / 分角色权限配置数据(可使用 aj jperm 生成各个角色权限数据。

i folder / i msexcel 目录

init/oob/role/LANG.YU/

@ / 自定义角色权限数据目录。

i bash 文件

init/oob/role/run-perm.sh

@ / 角色权限执行脚本。

i msexcel 文件

init/oob/environment.ambient.xlsx

@ 全局配置文件,对应 X_APP。

i msexcel 文件

init/oob/environment.menus.xlsx

@Deprecated 全局扩展菜单文件。

i folder / i json 目录

init/permission/ui.menu/

菜单权限配置文件(执行代码由系统生成)。

i json 文件

init/permission/ui.menu/ZERO_MENU_DISPLAY.json

人工可读菜单数据源,生成不同角色菜单专用。

i json 文件

init/permission/ui.menu/ZERO_MENU_SYSTEM.json

系统加载菜单数据源,生成不同角色菜单专用。

i yaml 文件

init/database.yml

(表生成主入口)Liquibase专用生成数据表配置文件。

i json 文件

init/environment.json

租户环境全局配置文件(AppId, Sigma, AppKey)。

i liquibase 文件

init/liquibase.properties

Liquibase数据库配置文件。

i folder / i java 目录

META-INF/services/

ServiceLoader专用配置文件夹,Java规范。

i folder / i java 目录

modulat/

模块化专用配置目录。

i folder / i plugin 目录

plugin/

插件专用目录。

i folder / i pojo 目录

pojo/

模型专用映射配置文件。

i folder / i runtime 目录

runtime/

运行时专用目录。

i folder / i workflow 目录

workflow/

工作流定义专用目录。

i workflow design 文件

workflow/<name>/workflow.pbmn

BPMN工作流定义文件。

i json 文件

workflow/<name>/*.json

工作流节点表单定义文件。

i form 文件

workflow/<name>/*.form

工作流节点表单文件,BPMN表单元数据定义文件。

i json 文件

workflow/<name>/workflow.history.json

工作流历史记录专用定义文件。

1.1.3.模块结构(nd-commerce)

若您安装了 vertx-ai 工具,可直接使用下边命令执行模块数据标准化生成所需的 initialize.json 文件(实践证明这个文件手写特别费时),您可以在任意时间段修改Excel配置数据内容包括文件删减,最终该命令会根据数据包中的内容执行配置文件标准化。模块名称:commerce,该名称会影响配置文件路径,整个环境中不允许重名模块出现。

# init-modulat.sh 脚本的内容
aj jmod -p src/main/resources/plugin/hotel/oob

模块的基本结构如下(带 task risk 为开发命令时有修改内容的部分):

类型 路径 说明

i folder 目录

script/

数据库初始化专用目录(遗留,就不参考最新标准执行)。

i xml 文件

script/code/config/zero-jooq.xml

task risk Jooq数据库生成代码的基础配置文件。

i bash 文件

script/code/zero.jooq.sh

Jooq数据库生成代码执行脚本,参考Zero教程下载依赖 jar 文件到该目录。

i bash 文件

script/database/database-reinit.sh

执行数据库建库脚本,被根目录 init-db.sh 调用。

i sql文件

script/database/database-reinit.sql

执行数据库建库SQL脚本,被 database-reinit.sh 调用。

i folder / i java 目录

src/main/java/

(Maven)Java代码文件。

i folder / i config 目录

src/main/resources/

(Maven)Java类路径、资源文件。

i bash 文件

init.db.sh

初始化数据库专用入口脚本。

i bash 文件

init-module.sh

模块化数据文件部署专用配置脚本。

  1. /script/code/ 目录中存放的JAR可从此处下载,Zero Framework 提取码: m99k,根据您的不同版本自己选择(推荐最新版,JDK 17+)。

  2. /script/database/ 目录中的脚本一般不用处理,最终会生成数据库:DB_ETERNAL,然后可执行代码生成并对接到数据库配置中,之后这个库就可直接移除。

  3. /init-module.sh 只有在更改模块配置的时候用。

1.1.3.1.代码结构

模块代码基础包结构如:

  • (上层)此处 cn.vertxup.xx 是Zero扫描入口(RESTful),一般不改动。

  • (下层)此处 com.<domain> 是Java规范中常用的按公司开发的模块包(核心业务逻辑)。

包名 说明

cn.vertxup.nd

接口层根包

cn.vertxup.nd.cv

常量池:@Address地址常量包,Pojo映射规范基础映射包。

cn.vertxup.nd.ke.booter

模块化配置器入口。

cn.vertxup.nd.micro

RESTful入口,@Endpoint/@Queue专用定义包,类似Spring中的@Controller。

cn.<domain>

模块核心组件包(业务逻辑)

cn.<domain>.atom

模型库:自定义建模(EMF或静态)包。

cn.<domain>.domain

实体库:Jooq自动生成,表模型。

cn.<domain>.error

容错定义:基于Zero容错框架的自定义异常信息。

cn.<domain>.optic

扩展槽:基于 ServiceLoader 扩展专用实现包、插件包。

cn.<domain>.refine

工具库:一般开放一个 双字母 类,做统一出口(类似Ux/Ut/Fn)。

cn.<domain>.service

业务层:类似Spring中的@Service。

cn.<domain>.uca

自定义组件:基于组件开发的核心组件包。

1.1.3.2.资源结构

模块资源基础目录结构如(前文提到过的此处直接写略):

类型 路径 功能

i folder / i json 目录

action/

(略)

i folder / i json 目录

authority/

(略)

i folder / i json 目录

cab/cn/

(略)

i folder / i json 目录

cab/directory/

(略)

i folder / i java 目录

META-INF/services/

(略)

i folder / i java 目录

modulat/

(略)

i folder / i plugin 目录

plugin/

(略)

i folder / i java 目录

plugin/commerce/oob/

模块核心配置数据目录,此处模块名称为:commerce,所以目录名也为 commerce。

i folder / i msexcel 目录

plugin/commerce/oob/cab/

@ / (略)只包含管理员角色权限数据。

i folder / i msexcel 目录

plugin/commerce/oob/data/

@ / (略)

i folder / i node 目录

plugin/commerce/oob/menu/

@ / (略)

i folder / i node 目录

plugin/commerce/oob/modulat/

@ / (略)

i folder / i json 目录

plugin/commerce/oob/module/crud/

@ / (略)

i folder / i json 目录

plugin/commerce/oob/module/ui/

@ / (略)

i folder / i msexcel 目录

plugin/commerce/oob/role/

@ / (略)只包含管理员角色权限数据。

i node 文件

plugin/commerce/oob/initialize.json

初始化配置,使用 aj jmod 可自动生成。

i yaml 文件

plugin/commerce/oob/initialize.yml

Jooq Dao配置,连接模块中需要导数据的模型配置。

i json 文件

plugin/commerce/oob/module.json

开启 /module/ 中功能的配置(CRUD模块化、UI列定义)。

i folder / i sql 目录

plugin/sql/commerce/

该模块包含的表SQL定义(liquibase会加载所有SQL文件)。

i liquibase 文件

plugin/sql/commerce.properties

「开发过程专用」Liquibase数据库配置文件。

i yaml 文件

plugin/sql/commerce.yml

(模块表生成入口)Liquibase专用生成数据表配置文件。

i folder / i pojo 目录

pojo/

(略)

i folder / i workflow 目录

workflow/

(略)

模块内资源结构基本和原始资源结构是保持一致,除开 plugin 内部有近似的部分,最终会导致所有模块运行在同一个环境中时,所有模块可以协同,不会出现系统匿名读取交叉配置的情况发生,这也是Zero Extension的核心设计思路。模块和模块之间由于目录不同所以相当于在主目录上挂载不同模块信息而已,如:

# 运行时插件配置
/plugin/commerce/           # commerce模块配置
/plugin/ambient/            # ambient模块配置

# 系统初始化配置
# commerce模块
/sql/commerce/              # commerce定义文件
/commerce.properties        # commerce独立配置文件
/commerce.yml               # commerce连接文件(真正生产环境使用的是此文件)
# ambient模块
/sql/ambient/
/ambient.properties
/ambient.yml

您也可以在此基础上扩展自定义的模块配置,如Zero Extension中每个模块根目录中都包含了 configuration.json 文件为扩展规范,但由于出现了 zero-bettery 中的 BAG/BLOCK 架构,后期是否已就需要此配置文件有待商榷。

1.1.4.启动器(nd-app)

1.1.4.1.自动化部署

新版启动器支持 ansible 方式一键部署,整个流程如下:

  1. 全项目编译,运行根项目中的 build.sh/build.bat 脚本。

  2. 基础设施准备:此准备过程参考环境搭建章节,主要是为项目初始化 数据库、云环境、第三方集成等,推荐使用 Terraform 模式。

  3. 配置数据准备:这是新版最大改动,直接运行启动器下的 run-ansible.sh/run-ansible.bat 脚本执行一键配置。

  4. Inst开发专用:根目录中 run-dev.sh 脚本主要用与帮助开发人员调试自动化部署工具,开发 指令集 专用。

先看启动器项目的目录结构:

类型 路径 功能

i folder 目录

app@history/

历史配置、测试配置、验证配置目录,无实际使用价值,可理解成回收站。

i folder 目录

app@jar/

从指令集中单独编译出来的可执行小工具,小工具通常在开发或生产中使用。

i folder 目录

app@runtime/

自动化运行时:包括自动化配置(开发环境)、自动化部署(生产环境)。

i folder 目录

app@runtime/@atom/

动态建模专用工作目录。

i folder / i msexcel 目录

app@runtime/@atom/meta

模型专用定义文件,文件名: <identifier>.xlsx 格式。

i folder / i json 目录

app@runtime/@atom/model

(系统自动生成)对应 M_MODEL 表的模型元数据。

i folder / i json 目录

app@runtime/@atom/schema

(系统自动生成)对应 M_ENTITY 表的实体元数据( 表模型 )。

i folder 目录

app@runtime/@source/

自动化运行组件共享数据目录。

i folder / i key 目录

keys/

证书目录。

i folder / i key 目录

keys/ipc/

微服务通信证书目录。

i folder / i java 目录

src/main/java/

(Maven)Java代码文件。

i folder / i config 目录

src/main/resources/

(Maven)Java类路径、资源文件。

i folder / i junit 目录

src/test/java/

(Maven)Java测试代码文件。

i folder / i config t 目录

src/test/resources/

(Maven)Java测试类路径、资源文件。

i env 文件

env.development.tpl

「模板」开发专用模板文件。

i git 文件

.gitignore

Git Ignore配置文件。

i pom 文件

pom.xml

Maven配置文件。

i bash 文件

run.ansible.sh

(一键配置入口)Ansible执行脚本。

i config 文件

run.env.sh.tpl

「模板」一键部署专用模板文件。

新版启动器中引入了 脱敏 机制,需要执行下边脚本将两个模板文件拷贝成正式文件(移除 .tpl 后缀)。

cp .env.development.tpl .env.development        # 运行时使用
cp run-env.sh.tpl run-env.sh                    # 一键配置使用

run-env.sh、.env.development 两个文件中包含了数据库账号密码等敏感信息、个人开发配置信息,二者已记录到 .gitignore 中不提交,所以每个人在使用时直接从模板文件拷贝并填上自己环境中的信息即可(一般初始化工程目录时提供,之后就不再变更,即使个人变更也不会影响其他人)。

1.1.4.2.代码结构

启动器中的基本结构是一致的,文件名都可以维持一致。

类全名 数据目录 说明

i bug cn.vertxup.develop.LoadCab

init/oob/cab/

(略)

i bug cn.vertxup.develop.LoadCmdb

init/oob/cmdb/

(略)

i bug cn.vertxup.develop.LoadData

init/oob/data/

(略)

i bug cn.vertxup.develop.LoadEnvironment

init/oob/environment/

(略)

i java cn.vertxup.develop.LoadWf

workflow

工作流配置加载(导入工作流定义)

i bug cn.vertxup.develop.LoadWfRule

activity-rule*.xlsx匹配文件

单独加载操作规则

i java cn.vertxup.develop.MenuData

x

菜单数据查看

i java cn.vertxup.develop.MenuOut

x

菜单数据输出(按角色分配输出,操作前文提到的角色数据)

i bug cn.vertxup.develop.MenuPermission

x

菜单角色权限单独导入

i java cn.vertxup.develop.ModInitializer

x

建模初始化:JSON → Database

i java cn.vertxup.develop.ModPre

x

建模准备:Excel → JSON

i bug cn.vertxup.develop.ModUi

identifier绑定数据

导入单个动态模型UI配置

i runtime cn.vertxup.ZoAgent

(开发专用)容器启动器

i bug cn.vertxup.ZoDebug

(开发专用)通用调试器

i run cn.vertxup.ZoEntry

生产环境主入口

i config cn.vertxup.ZoLoader

@Deprecated(开发专用)数据导入器,Ansible一键配置完成后可拿掉。

1.1.4.3.资源结构

启动器资源结构基本遵循前文提到的资源结构部分,但略微有些不同,此处主要针对资源目录中的特殊结构做一定说明(文件集

类型 路径 功能

i folder 目录

aeon

Zero Aeon云平台专用配置目录。

i yaml 文件

aeon/zapp.yml

Zero Aeon云平台连接模块主接口。

i folder / i json 目录

init/

(略)

i folder / i plugin 目录

plugin/

(略)

i folder / i pojo 目录

pojo/

(略)

i folder / i runtime 目录

runtime/

(略)

i logback 文件

logback.xml

运行日志配置(Logback)

i config 文件

vertx.yml

「内联」Zero容器主配置

i bug 文件

vertx-error.yml

「内联」Zero容错配置(系统级)

i bug 文件

vertx-readible.yml

「内联」Zero容错配置(用户级)

i plugin 文件

vertx-inject.yml

「内联」Zero核心插件配置

i config 文件

vertx-deployment.yml

扩展配置:Agent、Worker路由配置、开发调试配置、跨域配置

i config 文件

vertx-detect.yml

扩展配置:Jooq、Camunda、缓存、Trash删除备份、Redis、ES、Neo4j、组件监控

i config 文件

vertx-dock.yml

扩展配置:模块化部分/模块导入、初始化、加载、扩展组件

i config i key 文件

vertx-secure.yml

扩展配置:安全模块扩展

i config i msexcel 文件

vertx-excel.yml

扩展配置:Excel导入导出扩展

i config i bash 文件

vertx-shell.yml

扩展配置:Zero Shell框架,交互式命令行

扩展配置在 vertx.yml 的注释部分也包含相关说明:

  # 标准配置(不引入的)
  # - vertx-inject.yml      插件
  # - vertx-error.yml       系统错误定义
  # - vertx-readible.yml    人工错误定义
  # - vertx-server.yml      服务器(容器级)
  # 扩展配置(完整)
  # - vertx-excel.yml       Excel导入
  #     excel
  # - vertx-secure.yml      RBAC安全专用
  #     secure
  #     session
  # - vertx-shell.yml       DevOps命令行工具
  #     shell
  # 应用配置(每个应用不同)
  # - vertx-deployment.yml  开发部署(Agent、Worker、跨域、开发)
  #     cors                  跨域配置
  #     router                Agent路由
  #     deployment            Worker配置
  #     develop               开发专用配置
  # - vertx-detect.yml      集成(数据库、Redis、工作流、缓存、监控)
  #     jooq                  Jooq数据库访问
  #     workflow              Camunda工作流引擎
  #     cache                 缓存
  #     trash                 删除备份专用
  #     redis                 分布式缓存(配合缓存机制)
  #     elasticsearch         ES搜索服务
  #     neo4j                 Neo4J图数据库
  #     monitor               组件监控
  # - vertx-dock.yml        模块化(启动连接、初始化连接、模块加载、扩展组件)
  #     boot                  模块导入
  #     init                  模块初始化
  #     module                模块化加载
  #     extension             扩展组件
1.1.4.4.容器启动

容器启动主要注意下边界面的参数配置界面:

workflow boot
  1. 默认IDEA工作目录会是您的根项目(如图:hotel),此处应该修改成当前App的运行目录(启动器根目录)。

  2. 在开发环境中(监测到 .env.development),由于设置了环境变量,JDK9.0+的版本中,需在JVM Options中追加:

    --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED

最终启动成功之后您会在终端看到如下信息:

( Http Server ) ZeroHttpAgent Http Server has been started successfully. Endpoint: http://198.18.15.157:7085/.
1.1.4.5.环境变量

系统默认的环境变量文件此处提供代码注释

.env.development / .env.development.tpl

# --------------------- 环境变量专用区域 -----------------------
# 「Aeon」
# 云端资源环境变量
# -- 国外GitHub:  https://github.com/silentbalanceyh/vertx-zero-cloud.git
# -- 国内Gitee:   https://gitee.com/silentbalanceyh/vertx-zero-cloud.git
#
# AEON_CLOUD:基础资源专用环境变量(vertx-zero-cloud)
# -- 工作目录(一般是直接下载后的zero cloud工作目录)
# AEON_APP:应用资源专用目录(出厂设置,云设置)
#
# 这两个目录在容器内都需要支持共享模式,通过K8S的部署实现ConfigMap级别的分布式存储
# 共享,以确保环境中每一类应用的目录是固定的,这种模式下,路径协议变得很重要,此处
# 的路径必须支持路径协议,路径协议是高层处理,根据当前容器使用的SC决定。
# 默认路径规定:
#
AEON_CLOUD=/Users/lang/zero-cloud/vertx-zero-cloud/
AEON_APP=/Users/lang/zero-cloud/cloud-hotel/

# 「Zero」
# 应用级/应用级
# Z_APP:应用程序的code,作为系统路径,或表中的name字段对应
# Z_APP有了过后可以直接通过此一个数值决定其最终运行的环境值
# Z_APP对应的属性
# -- 语言                 多语言
# -- Sigma标识            多应用
# -- TenantID标识         多租户
# -- 前端路由               前端入口
# -- 后端路由               后端入口

# 「Container」
# Z_NS:             名空间信息
# Z_SIGMA:          统一标识符
# Z_LANG:           语言信息
# Z_NS=xxx
# Z_SIGMA=xxx
# X_LANG=cn
Z_APP=app.micro.hotel

# 「Deployment」
# 容器环境专用变量
# ----------------------- 跨域
Z_CORS_DOMAIN=http://ox.server.cn:7005

# ----------------------- RESTful
# Z_API_HOST: 主机地址,0.0.0.0表示任意IP都可访问
# Z_API_PORT: 后端端口
# Z_API_HOST=0.0.0.0
Z_API_PORT=7085

# ----------------------- Sock
# Z_SOCK_HOST: 主机地址,0.0.0.0
# Z_SOCK_PORT: 端口(默认直接挂在API上)
# Z_SOCK_HOST=0.0.0.0
# Z_SOCK_PORT=7085

# ----------------------- DB Service
# Z_DBS_HOST: 数据库连接主机地址
# Z_DBS_PORT: 数据库端口
# Z_DBS_INSTANCE:数据库实例名
# Z_DBS_HOST=ox.engine.cn
# Z_DBS_PORT=3306
# Z_DBS_INSTANCE=DB_HOTEL

# ----------------------- DB Workflow
# Z_DBW_HOST: 数据库连接主机地址
# Z_DBW_PORT: 数据库端口
# Z_DBW_INSTANCE:数据库实例名
# Z_DBW_HOST=ox.engine.cn
# Z_DBW_PORT=3306
# Z_DBW_INSTANCE=DB_HOTEL_WF

# ----------------------- DB History
# Z_DBH_HOST: 数据库连接主机地址
# Z_DBH_PORT: 数据库端口
# Z_DBH_INSTANCE:数据库实例名
# Z_DBH_HOST=ox.engine.cn
# Z_DBH_PORT=3306
# Z_DBH_INSTANCE=DB_HOTEL_HIS

# ----------------------- HED 模块(必须)
Z_HED_ENABLED=true
# ----------------------- 集成服务 System Integration Service
Z_SIS_STORE=/Users/lang/zero-cloud/runtime/store
环境变量名 说明

AEON_CLOUD

基础资源专用目录,通常是 Cloud工具箱 从Gitee下载后的项目内容空间。

AEON_APP

应用资源专用目录,当开启Aeon系统时,每个应用都会配套一个云端仓库地址,和前后端独立,该地址下载到本地之后使用此环境变量指定相关位置。

Z_APP

和前端一致指定当前运行的应用名称,对应 X_APP 中的 NAME 字段值。

Z_NS

应用名空间信息(开启zero-jet动态接口、任务之后必须使用该变量标识组件所属名空间)。

Z_SIGMA

统一标识符

Z_LANGE

当前系统使用的语言信息(默认cn)

Z_CROS_DOMAIN

(协同)开发过程指定当前应用前端跨域允许地址。

Z_API_HOST

「RESTful」后端指定Web服务器绑定IP地址,默认 0.0.0.0,无限制。

Z_API_PORT

「RESTful」开发协同、后端指定Web服务器端口。

Z_SOCK_HOST

「WebSocket」后端指定Sock服务器绑定IP地址,默认 0.0.0.0,无限制。

Z_SOCK_PORT

「WebSocket」开发协同、后端指定Sock服务器端口。

Z_DBS_HOST

「标准」数据库连接主机地址。

Z_DBS_PORT

「标准」开发协同、数据库端口号。

Z_DBS_INSTANCE

「标准」数据库实例名。

Z_DBW_HOST

「工作流」数据库连接主机地址。

Z_DBW_PORT

「工作流」开发协同、数据库端口号。

Z_DBW_INSTANCE

「工作流」数据库实例名。

Z_DBH_HOST

「历史」数据库连接主机地址。

Z_DBH_PORT

「历史」开发协同、数据库端口号。

Z_HED_ENABLED

HED加密模块设置,默认关闭,开启之后所有配置节点中的密码需使用密文。

Z_SIS_STORE

启用集成服务时所需的存储远程文件的路径名(环境变量优先于配置)。

run.env.sh / run.env.sh.tpl

#!/usr/bin/env bash
# 设置数据库类型(根据数据库类型执行不同流程)
# - 1) 现阶段脚本类型只支持 TIDB 和 MYSQL
# - 2) 远程机中已经部署了 mvn / java / mysql 三种命令
# - 3) 远程机中 non-shell 的环境变量已和 shell 登录模式保持了一致
#      检查远程环境中的 ~/.bashrc 中是否已包含了 mvn / java / mysql 三个命令的基础环境变量
# - 4) 默认数据库账号使用 zero,此处 DB_PASSWORD 对应的是 zero 的密码
# - 5) 默认 DB_ENV = DEV(开发测试环境)
# - 6) DB_ATOM开启动态建模部分
# - 7)Z_HED_ENABLED是否打开加密模块(默认关闭)
# TIDB / MYSQL
export DB_TYPE=MYSQL
export DB_PASSWORD=
export DB_ENV=DEV
export DB_ATOM=
export Z_HED_ENABLED=
环境变量名 说明

DB_TYPE

指定当前应用使用的数据库类型(不同类型脚本执行流程不一样),MYSQL、TIDB、PGSQL。

DB_PASSWORD

初始化数据库账号过程中使用的 zero 账号的密码。

DB_ENV

指定自动化部署的环境,DEV:开发部署,PROD:生产部署。

DB_ATOM

当前应用若开启了动态建模模块,则设置动态建模的应用名称(通常只有一个,若:cmdb),最终系统会从数据源目录:src/main/resources/atom/<DB_ATOM>/meta 中读取所有建模专用的Excel配置文件。

Z_HED_ENABLED

(同上)

  1. 此处设置的 DB_PASSWORD 不是 root 账号,而是系统默认的 zero 账号,您可以在第二章节中查看详细细节。

  2. DB_ATOM主要控制动态建模(步骤六),开启 zero-atom 动态建模流程,默认不开启。

  3. Z_HED_ENABLED控制系统中的数据库密码是否启用HED模块执行密码加密,若启用则密码必须以密文形式存放在配置文件中(否则使用明文,默认模式)。

  4. Z_HED_ENABLED环境变量还需注意的是开发模式下 .env.development 环境变量启动文件中必须相同设置,否则启动时候会连接数据库失败。

1.2.后端命名

1.3.前端结构规范

前端项目主要基于 Zero UI 框架进行定制和修改,您可以使用 ai init 命令执行此部分的初始化,最终生成的项目即为本章的核心项目结构——即:Zero UI前端脚手架

不改动的配置直接忽略不计,所有使用 yarn eject 出来的核心配置仅提供和Zero UI相关的配置信息,其他配置不在白皮书中讲解,您可以上网查询相关资料了解 yarn eject 命令结果的各文件职责。本规范三个章节的内容分别位于:

  • 项目结构:根目录说明

  • 自动化脚本:scripts目录说明

  • 源代码:src目录说明

1.3.1.项目结构

类型 路径 说明

i folder / i json 目录

.zero/

Zero Ai工具默认工作目录,配合 Zero Ai 工具箱工作。

i folder / i webpack 目录

config/

Webpack主配置目录,该目录来源于 yarn eject 命令结果。

i env 文件

config/env.js

环境变量连接专用脚本文件,.env.development / .env.production 双环境选择脚本。

i javascript 文件

config/modules.js

前端模块化专用JS配置,Zero UI模块化的 核心配置

i webpack 文件

config/webpack.config.js

前端Webpack主配置文件,Zero UI修改过的配置。

i folder / i asciidoc 目录

document/

AsciiDoc文档服务器专用目录。

i folder / i json 目录

document/doc-config/

JsDoc配置目录、AsciiDoc配置目录。

i folder / i asciidoc 目录

document/doc-source/

AsciiDoc源代码目录。

i folder / i html5 目录

document/doc-web/

git不提交)HTML5生成的AsciiDoc可查看静态源码目录。

i folder / i html5 目录

public/

应用静态站点目录,主骨架,包含了SPA入口:index.html。

i folder / i javascript 目录

scripts/

Zero UI启动脚本。

i folder / i java 目录

src/

Zero UI源代码目录。

i babel 文件

.babelrc

Babel专用转译配置文件,启用Babel环境的规范申明。

i env 文件

.env.development.tpl

协同开发环境环境变量模板文件(所有开发人员各自独立,使用时重命名)。

i env 文件

.env.production

生产环境变量文件。

i eslint 文件

.eslintignore

EsLint规范检查忽略文件,忽略声明的目录不做代码规范性检查。

i git 文件

.gitignore

(Zero UI定制)Git专用忽略文件,跳过声明文件不执行代码提交。

i npm 文件

package.json

项目基础信息定义文件。

i markdown 文件

README.md

首页Markdown介绍文件。

i bash 文件

run-cache.sh

清理缓存专用脚本。

i bash 文件

run-doc.sh

文档服务器,doc生成文档、server运行文档服务器。

i bash 文件

run-update.sh

包更新专用脚本。

i bash 文件

run-ux.sh

前端分发脚本。

i cmd 文件

run-zero.bat

Windows启动脚本。

i bash 文件

run-zero.sh

Linux/Unix启动脚本。

i markdown 文件

SUMMARY.md

Gitbook专用目录文件。

i tsconfig 文件

tsconfig.json

TypeScript配置文件。

1.3.2.自动化脚本

类型 路径 说明

i javascript 文件

scripts/build.js

生产构建专用脚本。

i javascript 文件

scripts/start.js

开发调试启动专用脚本。

i jest 文件

scripts/test.js

测试专用脚本。

i json 文件

scripts/zrun-package.json

包更新过滤设置,设置不更新的包,锁定版本专用。

i javascript 文件

scripts/zrun-route.js

自动化路由专用生成脚本。

1.3.3.环境变量

在ZeroUI中,环境变量用于控制不同环境的打包处理,脚手架中存在两个环境变量文件:.env.development.tpl / .env.production,在开发环境中由于每个人手中拿到的开发环境存在差异性,所以需要执行下边脚本才能进入正式流程开发:

# 准备开发环境变量文件
cp .env.development.tpl .env.development

上边步骤十分重要,若根目录没有 .env.development 文件会导致启动过程中无法加载正确的环境变量引起失败,且该文件存在于 .gitignore 文件中不会提交,每个人手中的文件则不会引起修改冲突。

当前ZeroUI中支持的环境变量表如下(您也可以参考 .env.development 中的注释信息):

环境变量名 类型 说明

PORT

原生

前端运行的端口号,若不设置会使用npm常用端口 3000

HOST

原生

前端开放可访问的HOST限制设置,不设置则采用 0.0.0.0,表示广域网可访问。

WSD_OK

原生

Websocket相关环境变量。

i core Z_APP

后端

应用系统名称,对应 X_APP 表中的name字段,读取默认应用配置的专用参数,多应用 环境中的应用标识。

i core Z_ENDPOINT

后端

后端远程RESTful的端地址,Ajax请求基地址。

i core Z_TITLE

后端

当前应用的默认标题,仅用于Webpack打包静态HTML模板时使用。

i core Z_LANGUAGE

后端

当前应用使用的语言信息,语音信息会对系统中的locale值产生影响,同时会影响远程加载配置的显示属性以及资源包的读取。

i core Z_X_HEADER_SUPPOER

后端

若启用了自定义头文件,则使用选项,会追加 X-App-Id,X-App-Key,X-Sigma,X-Tenant-Id,X-Lang 等自定义头(多语言、多应用、多租户、多样式 基础)。

i core Z_ROUTE

前端

React-Router路由基地址,代表应用本身,不同应用应该拥有不同的路由地址。

i core Z_K_SESSION

前端

SessionStorage中的会话前缀,多个账号访问同一浏览器时需要使用该前缀标识访问应用。

i core Z_K_EVENT

前端

Redux事件前缀,调试时可从事件前缀中查看当前Redux树来源于哪个应用。

i core Z_ENTRY_LOGIN

前端

特殊页面:登录页。

i core Z_ENTRY_ADMIN

前端

特殊页面:管理主页。

i core Z_ENTRY_FIRST

前端

特殊页面:密码修改页(首次登录所需)。

i core i config Z_PLUGIN

扩展

(目录 /app@plugin)是否启用插件。

i core i config Z_DEV_MOCK

扩展

(目录 /app@mock)是否启用模拟器,模拟器 可让您隔离后端运行独立前端(官方Demo使用了全Mock),可以代替Mock Server执行单接口调试。

i bug Z_DEV_MONITOR

开发调试

是否开启开发工具,若开启开发工具,使用快捷键 HOME 可直接调出调试控制台。

i bug Z_DEV_DEBUG

开发调试

是否打开常用调试日志。

i bug Z_DEV_AJAX

开发调试

是否打开后端交互调试日志。

i bug Z_DEV_FORM

开发调试

是否打开表单引擎调试日志。

i core Z_SHARED

样式

当前应用默认样式前缀,遵循此规则才可通过样式校验。

i core Z_CSS_COLOR

样式

全局默认色彩,动态样式中会受到工具的影响。

i core Z_CSS_FONT

样式

全局默认字体字号。

i core Z_CSS_RADIUS

样式

全局默认圆角矩形弧度设置(根据Ant 5.0规范支持2px, 4px, 6px, 8px,默认 6px)。

i config Z_CSS_SKIN_MODULE

样式

(实验版)动态样式中设置皮肤专用目录中的皮肤套件。

i config Z_CSS_SKIN_NAME

样式

(实验版)动态样式中皮肤名称,可设置深色或浅色模式。

i config Z_CSS_SKIN_TOOL

样式

(实验版)打开可调整样式的工具,现阶段开发启用,生产环境隐藏。

不论是在生产环境还是开发环境,带 i core 的环境变量都是必须配置的,若不配置核心环境变量有可能引起无法和您定制内容一致的问题导致启动失败。

1.3.4.源代码

1.3.集成规范

1.3.1.数据规范

1.3.2.联调

1.4.任务管理规范

任务管理统一使用登录 VPN 之后的管理平台,本章节主要针对项目管理过程中任务管理进行说明。

1.4.1.任务类型(Type)

任务类型参考下表

类型 分类 说明

SYSREQ System Requirement

标准文档

平台级开发需求说明书

SYSTC System Test Case

标准文档

平台集测试说明书

APPREQ Module Requirement

标准文档

应用模块开发需求说明书

APPTC Module Test Case

标准文档

应用模块测试说明书

RISK Run Risk

生命周期

风险评估报告,前期可行性分析专用

PKG Run Develop

生命周期

核心开发任务包,所有的Task在开发过程中全部任务隶属于此

UNIT Run Unit

生命周期

配合开发任务的单元测试任务

TC Run Test

生命周期

UAT测试、功能测试、性能测试任务专用

REL Run Release

生命周期

部署任务、发版本专用

BUG Fix Issue

运维

主要问题表」BUG修复,测试过程中问题提交到此类中

RFC Fix Change Request

运维

变更修复,新模块升级,新功能开发

RFC Task Common

执行过程

常用任务,无法分类的小任务归属于此

PERSONAL Task Personal

执行过程

个人任务,包括个人Demo、培训等

TPL Task Tpl

执行过程

模板任务,发放给所有人的模板任务

EXPLORER Task Explorer

执行过程

探索型任务,未知结果的POC等

OPS Task Operation

执行过程

运维脚本、数据导入导出所有运维类相关任务

1.4.2.任务命名

  1. 所有带有 @ 符号的任务为广播任务,广播任务表示每个人必须执行和完成的任务(自建任务模式)

    属性 默认值

    Type

    TPL Task Tpl

    Categories

    @SELF TASK

    Title

    通常使用@TPL前缀

    Severity

    Must Have

    Priority

    Highest

  2. 任务标题基本命名规范

    • 2.1.只有广播任务使用 @ 符号前缀。

    • 2.2.应用级任务使用各自应用前缀,如 APP / ISO 的任务标题使用 ISO/ 格式。

    • 2.3.任务标题中的数字带单位表示改任务的预估时间。

    • 2.4.个人任务全部使用 PT 前缀,个人任务可不填些任何时间相关信息。

  3. 所有任务最终会有一个期望,表示该任务的完成目标。 :data-uri:

1.5.前端样式规范

Ant Design 5.0采用了CSSinJS的方式处理样式信息,所以Zero UI最新版前端结构使用模块化的SASS/SCSS和它配合实现样式的整体定义,摒弃掉前一个版本的LESS技术,主要解决现阶段的一个核心问题:CSS全局污染问题——这个问题目前充斥着整个框架底层,由于最初的LESS规划不足,且LESS又不可能做到局部封闭,所以最终选择CSS Module技术(基于SASS/SCSS,采用Dart Sass引擎替换原始的node-sass)重新规划产品样式。

1.5.1.环境变量

样式相关的环境变量在前端中主要包含:

Z_CSS_SKIN_MODULE=HM                # 使用的皮肤模块名
Z_CSS_SKIN_NAME=NormLight           # 深色风格 / 浅色风格
Z_CSS_SKIN_TOOL=true                # 支持动态样式调整(带有样式工具栏)
Z_CSS_SHADOW=false                  # 窗口是否带阴影效果
Z_CSS_COLOR=#36648b                 # 系统默认主色调
Z_CSS_FONT=14                       # 字号大小
Z_CSS_RADIUS=4                      # Ant中默认是6,修正成4,基础组件的圆角设置

最终 WebPack 中产生的环境变量数据代码片段如下:

    /*
     * $uni_font    - 默认字体大小
     * $uni_color   - 默认关键色
     * $uni_radius  - 默认圆角尺寸(2 / 4 / 6 / 8)
     * $uni_shadow  - 默认是否开启阴影(true / false)
     */
    preOptions.additionalData = `
        $uni_font: ${process.env.Z_CSS_FONT}px;
        $uni_color: ${process.env.Z_CSS_COLOR};
        $uni_radius: ${process.env.Z_CSS_RADIUS}px;
        $uni_shadow: ${process.env.Z_CSS_SHADOW};
    `

不论是在生产环境还是开发环境,上述三个核心环境变量( Z_CSS_FONT、Z_CSS_RADIUS、Z_CSS_COLOR )是必须的,否则会导致SCSS注入失败引起启动问题。

WebPack中关于样式的路径和模块定义、使用流程如下:

    // config/modules.js 中定义
    skin: path.resolve(__dirname, "../src", "skin"),       // 皮肤管理器(最底层,由于zone存在控件定义)
    style: path.resolve(__dirname, "../src", "style"),     // 风格(SCSS导入用)

    // 使用代码
    import Sk from "skin";                                 // 风格API调用
    import __ from "./Cab.module.scss";                    // 动态导入:导入之后无法直接使用className类名引用
    import "./Cab.norm.scss";                              // 静态导入:导入之后可直接使用

1.5.2.全局风格(style)

全局风格文件位于style目录中,本章节描述全局风格文件的目录职责,不同职责目录入口文件都是 index.scss,相关说明在 style/index.scss 注释中。

类型 路径 说明

i folder 目录

style/connect

第三方样式表连接专用目录。

i css 文件

style/connect/mod.animate.css

动画效果专用CSS文件。

i folder / i sass 目录

style/function

通用样式函数。

i folder / i sass 目录

style/macrocosm

全局样式变量定义。

i sass 文件

style/macrocosm/mod.color.scss

全局色彩变量。

i sass 文件

style/macrocosm/mod.screen.scss

全局屏幕自适应变量。

i folder / i sass 目录

style/micrososm

局部可重用样式定义。

i folder / i sass 目录

style/module

模块样式定义。

i folder / i sass 目录

style/uca

组件样式定义。

i folder / i sass 目录

style/unstable

(自适应,screen前缀样式)。

i folder / i sass 目录

style/ux@legacy

旧样式替换目录(替换原始的 ux- 和 ex-)。

1.5.3.组件风格

前端页面和容器位于 components/container 目录中,这种类型的样式名会使用样式包 skin 中的API直接提取(CSS Module)。标准化组件类型的根样式则全部采用固定样式名,可直接在代码中用className引用,以 import "./Cab.norm.scss" 方式导入生效。

标准组件位于目录 /economy 中,所有扩展组件位于目录 /extension/ecosystem 中。

前缀 类型 说明

upg_

全局组件

(特殊)原 /extension/components 文件夹下所有扩展页面样式信息。

uni_

全局组件

如果可标准化的组件可直接使用该样式 uni_ 前缀,任何新项目都不用处理。

urd_

全局组件

开发中心专用样式表。

ux_

全局组件

整合原始 web- 和 ux- 构造的新规划的全局样式。

uca_

标准组件

标准自定义组件专用前缀名。

uex_

扩展组件

Ex 前缀型组件(Extension)

utx_

扩展组件

Tx 前缀型工作流专用组件(Task Of Workflow)。

umy_

扩展组件

My 前缀型个人设置专用组件(My Setting)。

uf_

扩展组件

F 前缀型财务专用组件(Finance Module)。

ug2_

扩展组件

G2 前缀型图表组件(G2)。

uix_

扩展组件

Ix (不对外)前缀型内置组件(Internal Component)。

uqx_

扩展组件

Qx 前缀型查询引擎组件(Query Engine Qr)。

uhx_

扩展组件

Hx 前缀型高阶配置组件(High Order of Configuration)。

uox_

扩展组件

Ox 前缀型配置组件,可使用动态建模(Origin Execute)。

样式特殊说明,上述样式中,除 upg_ 样式不可以使用类名的方式引用,其他样式都可以直接使用并且被重写。

1.5.4.样式详情

函数部分参考源代码查看 参数 相关信息,此处就不一一列举,新版由于在变量中会调用,所以将原始的中划线 - 统一修改成下划线实现变量调用;组件部分 带有 下划线 的为引用全局样式的类名。

1.5.4.1.全局函数
名称 类型 说明

attr_gradient_l

函数

水平渐变从左往右。

attr_gradient_r

函数

水平渐变从右往左。

attr_height_title

函数

标题高度设置(表单内可用)。

attr_shadow_box

函数

阴影处理。

unit_ant_btn_primary_100

函数

.ant-btn-primary的Ant样式修订,构造100%宽度的圆角大按钮。

unit_ant_button

函数

专用色彩按钮样式处理。

unit_ant_empty

函数

修订<Empty/>组件样式。

unit_date_picker

函数

针对时间日期选择器的背景色消除(去掉灰色)。

unit_selector_bg

函数

Selector选择器背景色消除(去掉灰色)。

unit_selector_input

函数

Selector内部背景色消除。

unit_tree_selected

函数

树型菜单中项选中之后样式(深色)。

uca_card_page

函数

Card组件专用,缩小边距的卡片样式设置。

uca_dash_app

函数

MyMenu中调用,专用于App入口样式设置。

uca_collapse

函数

Collapse组件专用风格。

uca_dialog

函数

Dialog组件专用(内置Modal),原版的web-dialog变种,主要设置弹窗风格和区域。

uca_drawer

函数

Drawer组件专用,原版窗口变种,主要设置抽屉风格和区域。

uca_popover

函数

Popover组件专用样式。

uca_popover_content

函数

Popover组件内容专用样式。

uca_form_error

函数

Zero UI特定的表单错误信息样式(浮游动画错误提示)。

uca_form_login

函数

登录表单专用样式。

uca_form_main

函数

主表单专用样式。

uca_form_readonly

函数

Form表单中字段只读样式。

uca_table_head

函数

列表头部专用函数,设置深色和浅色风格。

uca_bpmn_node

函数

流程图节点专用样式函数,前景色和背景色。

screen_uca_dialog

函数

带有自适应布局的Dialog组件专用样式。

screen_uca_popover

函数

带有自适应布局的Popover组件专用样式。

screen_uca_popover_content

函数

带有自适应布局的Popover内容组件专用样式。

1.5.4.2.全局类
  • uc前缀全称:Utility Color,主要负责色彩类className的独立定义。

  • ud前缀全称:Utility Dynamic,主要负责可变化类(带后缀)的相关定义。

  • ux前缀全称:Utility X(对应Zero中的Utility X部分),综合旧版本中的 ux-,ex-,ox-等相关className执行重构。

名称 类型 说明

uc_green

类名

色彩按钮:绿色。

uc_green_big

类名

(大号)色彩按钮:绿色。

uc_red

类名

色彩按钮:红色。

uc_pink

类名

色彩按钮:粉色。

uc_peach

类名

色彩按钮:桃红色。

uc_brown

类名

色彩按钮:棕色。

ud_column_cn${x}

类名

此处x为1 ~ 10,分别为x个中文字单元格宽度设置。

ux_addon_after

类名

输入框附加按钮专用样式。

ux_addon_disabled

类名

输入框禁用按钮专用样式。

ux_error

类名

错误信息样式。

ux_error_purge

类名

错误清除样式。

ux_op_search

类名

全局搜索框专用样式。

ux_op_ul

类名

全局横向链接菜单专用样式。

ux_op_transfer

类名

针对Transfer穿梭框的专用样式(拉满整行)。

ux_op_dbclick

类名

双击样式,对应原 ex-row-double。

ux_block

类名

左右侧页签标题专用样式,对应旧版 ex-blocks。

ux_hidden

类名

全局隐藏(display:none)专用样式,对应旧版 ux-hidden。

ux_disabled

类名

全局禁用专用样式。

ux_readonly

类名

全局只读专用样式,对应旧版 ux-readonly。

ux_readonly_select

类名

Selector可编辑(选择框只读)专用样式,消除背景用。

ux_readonly_unselect

类名

Selector只读专用样式。

ux_extra

类名

右上角附加操作区域专用样式,对应旧版 web-extra,多用于页签部分。

ux_title

类名

对应旧版 ux-title ux-title-pure 的组合样式。

ux_icon

类名

带文字的专用图标样式。

ux_view_my

类名

我的视图样式。

ux_card

类名

对应旧版 web-card。

ux_card_form

类名

对应旧版 web-card-form。

ux_form

类名

对应旧版 web-form。

ux_toolbar

类名

列表头部工具栏的主体样式信息。

ux_tab

类名

对应旧版 ex-tabs / web-tab。

ux_tab_block

类名

对应旧版 ex-tabs-tab-block。

ux_tab_container

类名

对应旧版 web-tab-container。

ux_tab_title

类名

对应旧版 web-tab-title。

ux_date_picker

类名

对应原版的 ux-select-readonly。

ux_select

类名

对应原版的 ux-select。

ux_table

类名

列表中表格专用样式,对应旧版 web-table。

ux_table_editor

类名

表格编辑器专用样式,对应旧版 web-table-editor。

ux_table_editor_small

类名

表格编辑器专用样式(小款),对应旧版 web-table-editor-small。

ux_table_tree

类名

表格中带字母树型结构专用样式。

ux_table_doc

类名

文档管理器中的表格专用样式。

ux_bag

类名

对应原版模块化专用处理。

ux_bpmn_end

类名

流程图完成节点。

ux_bpmn_error

类名

流程图异常节点。

ux_bpmn_active

类名

流程图激活节点。

ux_bpmn_hover

类名

(管理)鼠标移动到流程图节点。

ux_bpmn_selected

类名

(管理)流程图选中节点。

ux_popover_body

虚拟类名

(连接)父子优先级调整专用样式,针对内容。

ux_popover_footer

虚拟类名

(连接)父子优先级调整专用样式,针对页脚。

1.5.4.3.样式设计原则

基本设计原则如下:

  1. 前缀标识可直接针对不同类型的组件进行分类。

  2. 标准模式中只有 upg_动态模式,即不可以使用 className 直接引用。

  3. 如果是开发应用,需要使用自己的应用前缀如:[source, bash]`xc_, hm_, ox_`等。

参考下边代码对比 静态模式动态模式 的区别:

模式一:动态模式:标准样式中只有 upg_ 样式是这种类型,这种类型不可以直接引用。

// extension/components/integration/document/Cab.module.scss
.upg {
  &_integration_document {
  }
}
// 使用如:
import Sk from 'skin';
import __ from './Cab.module.scss';
....
    const attrs = Sk.mix(__.upg_integration_document);
    // 此处 attrs 已经包含了 className 和 style 属性,且是一个Object
    // 不可以在 jsx 中使用 className="upg_integration_document"
    return (
        <div {...attrs}/>
    )

模式二:静态模式:标准组件样式全使用此种模式。

// zion/variant/LoadingContent/Cab.norm.scss
.uca {
  &_LoadingContent {
    width: 100%;
    text-align: center;
  }
}
// 使用如:
import './Cab.norm.scss'
import Sk from 'skin';
....
    const attrs = Sk.mixUca("LoadingContent");
    // 此处 attrs 已经包含了 className 和 style 属性,且是一个Object
    // 且上述 className 为:uca_LoadingContent
    // 其他地方可以直接使用 className="uca_LoadingContent" 样式
        <div {...attrs}/>

自定义应用:components 和 container 必须使用第一种模式(被Hash的模式)以防止样式污染,标准化组件除开OOB页面以外,其他所有内容都使用模式二统一管理。

2. 环境搭建

2.1.准备工作

2.1.1.Zero Ai 工具

初始化工程之前先安装 Zero Ai工具,该工具提供了不同初始化工程的命令,可一键生成模板。

$ sudo npm install -g vertx-ai

初始化完成之后既可执行工程初始化命令分别初始化:后端、前端、后端插件(现阶段只支持三种类型)。

2.1.2.工程初始化

后端工程初始化暂时未提供工具,直接下载 vertx-zero-scaffold 脚手架项目,然后手工修改,后续版本中会提供一键命令进行。

前端工程初始化直接运行下边命令:

$ ai init -name <name>

后端插件初始化执行运行下边命令:

# -c 和 -p 两个参数可选
$ aj jplugin -m <name> -c <workspace.json> -p <path>

2.1.3.Cloud

您可以自己搭建云端开发环境,也可直接下载 Cloud工具箱 云端工具包执行云端工程的辅助开发。

$ git clone git@gitee.com:silentbalanceyh/vertx-zero-cloud.git

推荐您先下载 Cloud工具箱,其中包含了很多一键式自动化脚本以及云端开发的专用目录结构,本文后续章节全部依托该项目执行相关命令。Zero Cloud核心规范全部位于地址 Zero Aeon Cloud专用数据规范,该站点中包含了所有针对配置数据、定义的配置描述,系统可依赖它做配置、模型、定义以及元数据的各种校验。

Cloud在部署基础设施(Docker Compose模式)时,有三个脚本文件:

文件后缀(不带扩展) 含义

@up

执行docker-compose up -d

@down

执行docker-compose down

@stop

执行docker-compose stop

2.1.4.Ansible环境初始化

新版Zero使用了Ansible为开发人员准备一致性开发环境,但基础准备工作需要在此处特殊说明,开发环境的Ansible执行流程图如下:

Fork

Ansible基本准备工作如下:

  1. 目标机器(开发环境本地,生产环境服务器)需配置三个核心命令:mysql、mvn、java(开发环境初始化只需要mysql,java、mvn为将来准备着)。

  2. 由于Ansible使用登录方式为Non Shell,所以上述三个核心命令的配置需要配置在目标机器的 ~/.bashrc 环境变量文件中,如:

    # Ansible ------------------------------------------------------------------
    # Ansible Java
    export JAVA_HOME=/Library/Java/JavaVirtualMachines/zulu-17.jdk/Contents/Home
    export CLASSPATH=.
    export PATH=$PATH:$JAVA_HOME/bin
    # Ansible Homebrew
    # - MySQL, Maven .....
    export PATH=$PATH:/opt/homebrew/bin
  3. 在执行 ansible 命令的机器配置 /etc/ansible/hosts 设置需操作的主机信息,如:

    [zero]
    ox.engine.cn            # 该地址也已经写入本机host中:127.0.0.1 -> ox.engine.cn

从流程图上可知,前半部分 账号初始化、库初始化 在生产环境和开发环境是一致的,都是使用SSH登录到目标机器执行脚本(Windows会重新开发),后半部分 表初始化、数据初始化 在开发环境使用 liquibase、iac-load.jar 直接执行,而在生产环境则会将初始化内容打包成发布专用的SQL文件,直接执行。

2.2.数据库(开发环境)

本章节主要讲解Zero中数据库初始化流程,默认账号密码如:

类型 账号 说明

MySQL / TiDB

root

root账号

MySQL / TiDB

zero

核心管理员账号

2.2.1.MySQL 8.0

2.2.1.1.Docker-Compose

进入到zone@docker/database-dc-mysql-8目录中,该目录中包含了MySQL的Docker-Compose基础配置,为了脱敏操作,下载的版本中没有环境变量文件 zero-mysql-8.env,您可以直接将目录中的模板文件拷贝一份:

$ cd zone@docker/database-dc-mysql-8
$ cp tpl.zero-mysql-8.env zero-mysql-8.env

使用工具或IDE编辑您的两个账号的初始密码:

MYSQL_ROOT_PASSWORD=
MYSQL_ROOT_HOST=%
MYSQL_USER=zero
MYSQL_PASSWORD=
参数 含义

MYSQL_ROOT_PASSWORD

root账号密码

MYSQL_ROOT_HOST

root账号访问的host设置,最终为 root@host中host部分

MYSQL_USER

新建MySQL账号名

MYSQL_PASSWORD

新建MySQL账号对应密码(初始化执行即为zero账号授权)

然后执行如下命令启动MySQL:

$ ./zero-mysql-8-@up.sh

运行成功后,您可以使用工具连接MySQL(确认zero/root双账号可连接)。

$ mysql -u zero -P 3306 -h ox.engine.cn
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 11
Server version: 8.0.27 MySQL Community Server - GPL

Copyright (c) 2000, 2023, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>

确认您的 zero 账号执行过 init 下的初始化脚本,该脚本会为 zero 账号执行授权,您可以在MySQL中查看该账号是否授权成功。

2.2.1.2.Terraform

进入到zone@terraform目录中,该目录中包含了MySQL的所有terraform脚本,为了脱敏操作,下载版本中没有设置环境变量文件 initialize.sh,您可以直接将目录中的 tpl.initialize.sh 拷贝一份:

$ cd zone@terraform/kmini/database-mysql-8
$ cp tpl.initialize.sh initialize.sh

使用工具或IDE编辑您的两个账号的初始密码,编辑 initialize.sh(属性同上,此处不累赘)。

#!/usr/bin/env bash
export TF_VAR_mysql_password=
export TF_VAR_mysql_root_password=
export TF_VAR_mysql_data_path=${PWD}/data

# 编辑完成后执行
$ source ./initialize.sh

然后在目录中依次执行下边命令:

# 初始化所有资源
$ terraform init

Initializing the backend...

Initializing provider plugins...
- Finding kreuzwerker/docker versions matching "3.0.1"...
- Installing kreuzwerker/docker v3.0.1...
- Installed kreuzwerker/docker v3.0.1 (self-signed, key ID BD080C4571C6104C)

Partner and community providers are signed by their developers.
If you''d like to know more about provider signing, you can read about it here:
https://www.terraform.io/docs/cli/plugins/signing.html

Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

# 查看执行计划
$ terraform plan

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # docker_container.terraform-mysql-8 will be created
  + resource "docker_container" "terraform-mysql-8" {
      + attach                                      = false
      + bridge                                      = (known after apply)
      + command                                     = (known after apply)
      + container_logs                              = (known after apply)
      + container_read_refresh_timeout_milliseconds = 15000
      + entrypoint                                  = (known after apply)
      + env                                         = [
          + "MYSQL_PASSWORD=pl,okm123YH",
          + "MYSQL_ROOT_HOST=%",
          + "MYSQL_ROOT_PASSWORD=pl,okmijn123",
          + "MYSQL_USER=zero",
        ]
      + exit_code                                   = (known after apply)
      + hostname                                    = "ox.engine.cn"
      + id                                          = (known after apply)
      + image                                       = "mysql:8.0.32"
      + init                                        = (known after apply)
      + ipc_mode                                    = (known after apply)
      + log_driver                                  = (known after apply)
      + logs                                        = false
      + must_run                                    = true
      + name                                        = "terraform-mysql-8"
      + network_data                                = (known after apply)
      + read_only                                   = false
      + remove_volumes                              = true
      + restart                                     = "no"
      + rm                                          = false
      + runtime                                     = (known after apply)
      + security_opts                               = (known after apply)
      + shm_size                                    = (known after apply)
      + start                                       = true
      + stdin_open                                  = false
      + stop_signal                                 = (known after apply)
      + stop_timeout                                = (known after apply)
      + tty                                         = false
      + wait                                        = false
      + wait_timeout                                = 60

      + healthcheck {
          + interval     = (known after apply)
          + retries      = (known after apply)
          + start_period = (known after apply)
          + test         = (known after apply)
          + timeout      = (known after apply)
        }

      + labels {
          + label = (known after apply)
          + value = (known after apply)
        }

      + networks_advanced {
          + aliases = []
          + name    = "mysql_network"
        }

      + ports {
          + external = 3306
          + internal = 3306
          + ip       = "0.0.0.0"
          + protocol = "tcp"
        }

      + upload {
          + content    = <<-EOT
                GRANT ALL PRIVILEGES ON *.* TO 'zero'@'%';
                FLUSH PRIVILEGES;
            EOT
          + executable = true
          + file       = "/docker-entrypoint-initdb.d/account.sql"
        }
    }

  # docker_image.mysql will be created
  + resource "docker_image" "mysql" {
      + id           = (known after apply)
      + image_id     = (known after apply)
      + keep_locally = true
      + name         = "mysql:8.0.32"
      + repo_digest  = (known after apply)
    }

  # docker_network.private_network will be created
  + resource "docker_network" "private_network" {
      + driver      = (known after apply)
      + id          = (known after apply)
      + internal    = (known after apply)
      + ipam_driver = "default"
      + name        = "mysql_network"
      + options     = (known after apply)
      + scope       = (known after apply)

      + ipam_config {
          + aux_address = (known after apply)
          + gateway     = (known after apply)
          + ip_range    = (known after apply)
          + subnet      = (known after apply)
        }
    }

Plan: 3 to add, 0 to change, 0 to destroy.

─────────────────────────────────────────────────────────────────────────────────────────────

Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run "terraform apply" now.

# 部署
$ terraform apply

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

docker_network.private_network: Creating...
docker_image.mysql: Creating...
docker_image.mysql: Creation complete after 0s [id=sha256:05b458cc32b9686508b97ef40043702c18572840f7b2936b14f06500363868bamysql:8.0.32]
docker_network.private_network: Creation complete after 2s [id=b6285a9e627492f19fcd001830ddd04a6af1e5df4a6c6aeb501ab0965ce6cf45]
docker_container.terraform-mysql-8: Creating...
docker_container.terraform-mysql-8: Creation complete after 1s [id=b651230638dd8bd576b5ac54bd2edca751154ddafcfd12b1201da6be0e1956e6]

Apply complete! Resources: 3 added, 0 changed, 0 destroyed.

上述命令执行完成后,您就可以使用客户端连接新的MySQL容器了。

先确认您使用Docker Compose运行的MYSQL容器已经停止运行 docker-compose …​ stop,再执行Terraform版本,由于两个版本使用了相同的宿主机3306端口号,若不停止运行可能会导致创建失败,细心的您会发现Terraform模式下的MySQL并未指定数据目录和日志目录,原因是此处只是为了开发环境使用,详细用法参考 valumes,若您想要删除资源可直接使用下边命令:

terraform destroy

本章节是第一次使用terraform章节,所以在代码部分我保留了三次执行结果,后续章节再使用terraform时则我会直接忽略不再提供执行结果!

最后还有一个点需要注意,就是 providers.tf 中的代码,由于我使用的MacOS平台,所以此处的值要根据您运行Docker的平台有所变化:

provider "docker" {
  host = "unix:///private/var/run/docker.sock"
}

2.2.2.PgSQL

  • 由于MySQL 5.x和8.x差距比较大,所以才在文件目录中带上了版本号,PgSQL则不需使用版本号标识,直接换镜像名称既可。

  • 如果您使用的是MacOS系统,您可以直接安装 Postgres.app 运行PgSQL(绿色软件)。

2.2.2.1.Docker-Compose

进入到zone@docker/database-dc-pgsql目录中,该目录中包含了MySQL的Docker-Compose基础配置,为了脱敏操作,下载的版本中没有环境变量文件 zero-pgsql.env,您可以直接将目录中的模板文件拷贝一份:

$ cd zone@docker/database-dc-pgsql
$ cp tpl.zero-pgsql.env zero-pgsql.env

使用工具或IDE编辑您的账号的初始密码:

POSTGRES_PASSWORD=
POSTGRES_USER=postgres
POSTGRES_DB=postgres
TZ=Asia/Shanghai
参数 含义

POSTGRES_PASSWORD

postgres账号密码

POSTGRES_USER

默认账号名

POSTGRES_DB

默认账号访问的Schema名

TZ

默认使用的时区

然后执行如下命令启动PgSQL:

$ ./zero-pgsql-@up.sh
2.2.2.2.Terraform

进入到zone@terraform目录中,该目录中包含了PgSQL的所有terraform脚本,为了脱敏操作,下载版本中没有设置环境变量文件 initialize.sh,您可以直接将目录中的 tpl.initialize.sh 拷贝一份:

$ cd zone@terraform/kmini/database-pgsql
$ cp tpl.initialize.sh initialize.sh

使用工具或IDE编辑您的两个账号的初始密码,编辑 initialize.sh(属性同上,此处不累赘)。

#!/usr/bin/env bash
export TF_VAR_pgsql_password=
export TF_VAR_pgsql_data_path=${PWD}/data

# 编辑完成后执行
$ source ./initialize.sh

然后在目录中依次执行下边命令就可以部署好PgSQL的Docker版本了:

$ terraform init
$ terraform plan
$ terraform apply

注意 main.tf 中关于网络的代码:

resource "docker_network" "private_network" {
  name = "mysql_network"
}

如果只部署一个是没有问题的,但若在同一个Docker中同时运行MySQL和PgSQL,此处需要修改

resource "docker_network" "mysql_network" {
  name = "mysql_network"
}

否则:Docker 容器无法定位网络使用的哪一个导致 terraform apply命令执行失败!

2.2.3.TiDB

2.2.3.1.Docker Compose

TiDB的Docker Compose版本已经在Cloud工具箱中存在,您可以直接进入zone@docker/database-dc-tidb启动TiDB集群,但由于该集群所需资源比较高昂,所以不建议使用DC方式运行TiDB,当然您机器性能很好就另当别论,最好确认 14个容器 全部在Docker中正常启动,再使用才不会有问题。

2.2.3.2.TiUP启动

TiDB官方提供了两种快速上手模式(开发环境和生产环境单机运行就不用考虑了,参考 软硬件环境需求 )。直接进入zone@os/database-os-tidb目录中,先更新TiUP Cluster的所有组件:

$ tiup update --self && tiup update cluster

然后直接运行启动脚本:

# tiup playground v6.5.0 --db 2 --pd 3 --kv 3 --tag tidb-zero
$ ./tidb-start.sh
tiup is checking updates for component playground ...
Starting component `playground`: /Users/lang/.tiup/components/playground/v1.11.2/tiup-playground v6.5.0 --db 2 --pd 3 --kv 3 --tiflash 0 --tag tidb-zero
Playground Bootstrapping...
Start pd instance:v6.5.0
Start pd instance:v6.5.0
Start pd instance:v6.5.0
Start tikv instance:v6.5.0
Start tikv instance:v6.5.0
Start tikv instance:v6.5.0
Start tidb instance:v6.5.0
Start tidb instance:v6.5.0
Waiting for tidb instances ready
127.0.0.1:4000 ... Done
127.0.0.1:4001 ... Done
CLUSTER START SUCCESSFULLY, Enjoy it ^-^
To connect TiDB: mysql --comments --host 127.0.0.1 --port 4001 -u root -p (no password)
To connect TiDB: mysql --comments --host 127.0.0.1 --port 4000 -u root -p (no password)
To view the dashboard: http://127.0.0.1:2379/dashboard
PD client endpoints: [127.0.0.1:2379 127.0.0.1:2382 127.0.0.1:2384]
To view the Prometheus: http://127.0.0.1:9090
To view the Grafana: http://127.0.0.1:3000

看到上边界面后就可以直接连接4000端口进入TiDB了(默认root密码"")。

3. 配置/实施

3.1.基础环境配置

3.2.前端静态配置

3.3.前端动态配置(zero-ui)

3.4.前端组件

3.5.开发中心插件

3.6.CRUD模板(zero-crud)

3.7.ACL权限管理(zero-rbac)

白皮书中的权限管理主要包括两部分:管理端和消费端

  • 管理端:可扩展面板式架构,现阶段版本支持 菜单管理、流程定制 两类,您可以扩展自己所需的不同权限管理的结构。

  • 消费端:XBAC模型:基于角色的RBAC(Role)、基于属性的ABAC(Attribute)、基于策略的PBAC(Policy)。

Zero在线教程中讲解过可插拔模式的认证组件,此处略过认证部分(@Wall ),本书主要讲解扩展模块中的授权以及 zero-rbac 模块如何实现企业级需求的复杂授权流程,其中标准化认证采用了 OAuth 规范。

3.7.1.消费端

3.7.1.1.XBAC模型

Zero中的基本权限主体模型如下:

zarch perm

上图中的核心概念如下:

实体表 概念 含义

S_USER

用户

登录系统专用账号信息表。

S_ROLE

角色

和账号关联的角色信息表。

S_GROUP

用户组

和账号关联的用户组信息表。

S_PERMISSION

权限

和角色相关联的权限记录表。

S_PERM_SET

权限集

服务于权限定义的权限集合表,主要用于管理段构造权限集合实现批量授权。

S_ACTION

操作

隶属于权限记录的操作集合,操作最终会绑定到对应的操作主体上。

  • 所有关联表(R_ 前缀)目前都是多对多结构,一个用户可关联多个角色,一个用户可关联多个用户组,一个用户组关联多个角色,一个角色关联多个权限记录,一个权限记录包含多个 安全操作

  • 用户组支持继承结构,包括父组和子组的概念,权限计算过程中,不同算法在父子级结构中发挥的作用会有所区别。

  • 角色和用户组关联过程中支持优先级,即用户在关联角色和用户组时存在 第一角色、第一用户组 的概念。

常用的基本配置中,只要资源所需操作级别和基础算法模型计算的最终权限路径和用户所拥有的权限路径是通的,那么就可以实现基础权限的认证,这部分内容在完成本章节所有讲解之后会有更深入的说明。

安全操作 S_ACTION 对端关联到资源表 S_RESOURCE 和资源形成1对1的绑定,资源中定义的就是访问资源的基本要求,而S_ACTION中计算出来的结果就是登录账号所拥有的资源访问资格,当资源访问资格满足了资源基本要求时就认证通过,证明当前账号有权限访问该资源。但是、但是、但是——此处只是解决了账号:能不能 的问题,在资源访问之后还会有两张专用的数据表来执行 访问多少 的问题,这是Zero中数据域的实现原理,在后续的 N维安全视图 中加以说明。

3.7.1.2.多态身份(Profile)

Zero中由于复杂的多对多结构,最终会形成不同的多态身份(Profile),S_RESOURCE 表中有如下字段对资源访问资格执行定义:

字段名 含义 取值

MODE_ROLE

按角色查找资源的模式

UNION、EAGER、LAZY、INTERSECT

MODE_GROUP

按用户组查找资源的模式

HORIZON、CRITICAL、OVERLOOK

MODE_TREE

用户组继承和非继承树模式查找

EXTEND、PARENT、CHILD、INHERIT

上述取值是资源对多态身份的定义,最终形成的多态身份 Profile 的值列表如下(举例定义角色和组的优先级):

  • 多态身份只有在多角色、关联用户组、多用户组模式下生效,如果只包含一个角色,多态身份会演变成最简单的 USER_UNION 模式。

  • 用户/角色、用户组/角色在计算时都支持 UNION, EAGER, LAZY, INTERSECT 四种模式。

  • 使用用户组模式时,只要计算出选择使用什么用户组,就可以执行用户组对应的角色关联权限集的计算。

不含组模式

假设用户包含如下信息,这种模式(高频使用模式)下 MODE_GROUP / MODE_TREE 都设置成 NULL

R1(H):P1、P2、P3,高优先级角色,包含三条权限记录。
R2(L):P2、P4,低优先级角色,包含两条权限记录。

zero p user

含义

USER_UNION

zero p user union 并集模式,最终权限集为 P1, P2, P3, P4

USER_EAGER

zero p user eager 高优先级模式,使用最高优先级角色的权限集,此处:P1, P2, P3

USER_LAZY

zero p user lazy 低优先级模式,使用最低优先级角色的权限集,此处:P2, P4

USER_INTERSECT

zero p user intersect 交集模式,最终权限集为 P2

用户组模式

假设用户包含如下信息:

用户组结构如下(此处不列举组所对应的权限集):
         G10
        /   \
      G20   G21
     /   \    \
    G30  G31  G32
而登录用户只包含如下三个用户组:
G20(H):高优先级用户组
G31(M):中优先级用户组
G32(L):低优先级用户组
全量优先级:
G10 > G20 > G21 > G30 > G31 > G32

zero p group

组计算 角色计算 计算流程

HORIZON_UNION

zero p group u

zero p user union

UNION模式计算单个用户组关联角色权限集,再将三个组的权限集合并。

HORIZON_EAGER

zero p group u

zero p user eager

EAGER模式计算单个用户组关联角色权限集,再将三个组的权限集合并。

HORIZON_LAZY

zero p group u

zero p user lazy

LAZY模式计算单个用户组关联角色权限集,再将三个组的权限集合并。

HORIZON_INTERSECT

zero p group u

zero p user intersect

INTERSECT模式计算单个用户组关联角色权限集,再将三个组的权限集合并。

CRITICAL_UNION

zero p group h

zero p user union

UNION模式计算高优先级组的权限集。

CRITICAL_EAGER

zero p group h

zero p user eager

EAGER模式计算高优先级组的权限集。

CRITICAL_LAZY

zero p group h

zero p user lazy

LAZY模式计算高优先级组的权限集。

CRITICAL_INTERSECT

zero p group h

zero p user intersect

INTERSECT模式计算高优先级的权限集。

OVERLOOK_UNION

zero p group l

zero p user union

UNION模式计算低优先级组的权限集。

OVERLOOK_EAGER

zero p group l

zero p user eager

EAGER模式计算低优先级组的权限集。

OVERLOOK_LAZY

zero p group l

zero p user lazy

LAZY模式计算低优先级组的权限集。

OVERLOOK_INTERSECT

zero p group l

zero p user intersect

INTERSECT模式计算低优先级组的权限集。

PARENT_HORIZON_UNION

zero p parent gu

zero p user union

先查找三个组的父组,再按UNION模式计算权限集。

PARENT_HORIZON_EAGER

zero p parent gu

zero p user eager

先查找三个组的父组,再按EAGER模式计算权限集。

PARENT_HORIZON_LAZY

zero p parent gu

zero p user lazy

先查找三个组的父组,再按LAZY模式计算权限集。

PARENT_HORIZON_INTERSECT

zero p parent gu

zero p user intersect

先查找三个组的父组,再按INTERSECT模式计算权限集。

PARENT_CRITICAL_UNION

zero p parent gh

zero p user union

查找优先级最高组的父组,再按UNION模式计算权限集。

PARENT_CRITICAL_EAGER

zero p parent gh

zero p user eager

查找优先级最高组的父组,再按EAGER模式计算权限集。

PARENT_CRITICAL_LAZY

zero p parent gh

zero p user lazy

查找优先级最高组的父组,再按LAZY模式计算权限集。

PARENT_CRITICAL_INTERSECT

zero p parent gh

zero p user intersect

查找优先级最高组的父组,再按INTERSECT模式计算权限集。

PARENT_OVERLOOK_UNION

zero p parent gl

zero p user union

查找优先级最低组的父组,再按UNION模式计算权限集。

PARENT_OVERLOOK_EAGER

zero p parent gl

zero p user eager

查找优先级最低组的父组,再按EAGER模式计算权限集。

PARENT_OVERLOOK_LAZY

zero p parent gl

zero p user lazy

查找优先级最低组的父组,再按LAZY模式计算权限集。

PARENT_OVERLOOK_INTERSECT

zero p parent gl

zero p user intersect

查找优先级最低组的父组,再按INTERSECT模式计算权限集。

CHILD_HORIZON_UNION

zero p child gu

zero p user union

查找所有组的子组,再按UNION模式计算权限集。

CHILD_HORIZON_EAGER

zero p child gu

zero p user eager

查找所有组的子组,再按EAGER模式计算权限集。

CHILD_HORIZON_LAZY

zero p child gu

zero p user lazy

查找所有组的子组,再按LAZY模式计算权限集。

CHILD_HORIZON_INTERSECT

zero p child gu

zero p user intersect

查找所有组的子组,再按INTERSECT模式计算权限集。

CHILD_CRITICAL_UNION

zero p child gu

zero p user union

查找优先级最高组的子组,再按UNION模式计算权限集。

CHILD_CRITICAL_EAGER

zero p child gu

zero p user eager

查找优先级最高组的子组,再按EAGER模式计算权限集。

CHILD_CRITICAL_LAZY

zero p child gu

zero p user lazy

查找优先级最高组的子组,再按LAZY模式计算权限集。

CHILD_CRITICAL_INTERSECT

zero p child gu

zero p user intersect

查找优先级最高组的子组,再按INTERSECT模式计算权限集。

CHILD_OVERLOOK_UNION

zero p child gl

zero p user union

(无权限)查找优先级最低组的子组,再按UNION模式计算权限集。

CHILD_OVERLOOK_EAGER

zero p child gl

zero p user eager

(无权限)查找优先级最低组的子组,再按EAGER模式计算权限集。

CHILD_OVERLOOK_LAZY

zero p child gl

zero p user lazy

(无权限)查找优先级最低组的子组,再按LAZY模式计算权限集。

CHILD_OVERLOOK_INTERSECT

zero p child gl

zero p user intersect

(无权限)查找优先级最低组的子组,再按INTERSECT模式计算权限集。

INHERIT_HORIZON_UNION

zero p inherit gu

zero p user union

查找所有组父组包含本组,再按UNION模式计算权限集。

INHERIT_HORIZON_EAGER

zero p inherit gu

zero p user eager

查找所有组父组包含本组,再按EAGER模式计算权限集。

INHERIT_HORIZON_LAZY

zero p inherit gu

zero p user lazy

查找所有组父组包含本组,再按LAZY模式计算权限集。

INHERIT_HORIZON_INTERSECT

zero p inherit gu

zero p user intersect

查找所有组父组包含本组,再按INTERSECT模式计算权限集。

INHERIT_CRITICAL_UNION

zero p inherit gh

zero p user union

查找优先级高组的父组包含本组,再按UNION模式计算权限集。

INHERIT_CRITICAL_EAGER

zero p inherit gh

zero p user eager

查找优先级高组的父组包含本组,再按EAGER模式计算权限集。

INHERIT_CRITICAL_LAZY

zero p inherit gh

zero p user lazy

查找优先级高组的父组包含本组,再按LAZY模式计算权限集。

INHERIT_CRITICAL_INTERSECT

zero p inherit gh

zero p user intersect

查找优先级高组的父组包含本组,再按INTERSECT模式计算权限集。

INHERIT_OVERLOOK_UNION

zero p inherit gl

zero p user union

查找优先级低组的父组包含本组,再按UNION模式计算权限集。

INHERIT_OVERLOOK_EAGER

zero p inherit gl

zero p user eager

查找优先级低组的父组包含本组,再按EAGER模式计算权限集。

INHERIT_OVERLOOK_LAZY

zero p inherit gl

zero p user lazy

查找优先级低组的父组包含本组,再按LAZY模式计算权限集。

INHERIT_OVERLOOK_INTERSECT

zero p inherit gl

zero p user intersect

查找优先级低组的父组包含本组,再按INTERSECT模式计算权限集。

EXTEND_HORIZON_UNION

zero p extend gu

zero p user union

查找所有组子组包含本组,再按UNION模式计算权限集。

EXTEND_HORIZON_EAGER

zero p extend gu

zero p user eager

查找所有组子组包含本组,再按EAGER模式计算权限集。

EXTEND_HORIZON_LAZY

zero p extend gu

zero p user lazy

查找所有组子组包含本组,再按LAZY模式计算权限集。

EXTEND_HORIZON_INTERSECT

zero p extend gu

zero p user intersect

查找所有组子组包含本组,再按INTERSECT模式计算权限集。

EXTEND_CRITICAL_UNION

zero p extend gh

zero p user union

查找优先级高组的子组包含本组,再按UNION模式计算权限集。

EXTEND_CRITICAL_EAGER

zero p extend gh

zero p user eager

查找优先级高组的子组包含本组,再按EAGER模式计算权限集。

EXTEND_CRITICAL_LAZY

zero p extend gh

zero p user lazy

查找优先级高组的子组包含本组,再按LAZY模式计算权限集。

EXTEND_CRITICAL_INTERSECT

zero p extend gh

zero p user intersect

查找优先级高组的子组包含本组,再按INTERSECT模式计算权限集。

EXTEND_OVERLOOK_UNION

zero p extend gl

zero p user union

查找优先级低组的子组包含本组,再按UNION模式计算权限集。

EXTEND_OVERLOOK_EAGER

zero p extend gl

zero p user eager

查找优先级低组的子组包含本组,再按EAGER模式计算权限集。

EXTEND_OVERLOOK_LAZY

zero p extend gl

zero p user lazy

查找优先级低组的子组包含本组,再按LAZY模式计算权限集。

EXTEND_OVERLOOK_INTERSECT

zero p extend gl

zero p user intersect

查找优先级低组的子组包含本组,再按INTERSECT模式计算权限集。

多态身份Profile是整个 Zero权限框架中的一个 过度设计 的典范,从实际场景看起来真正使用到这部分的内容仅局限于 USER_X 四种计算模式。但根据设计时的调研和考察,有这部分功能之后,对于复杂组织架构之间的权限控制可以达到非常细粒度的级别,并且在变化过程中,可实现更多变化模式下的权限控制。

对用户而言,一旦登录之后,自己的 Profile 就已经固定,而资源需求要求的Profile则不一定固定,属于变量,最终计算结果近似于查找最短路径,达到用户组这个级别的额外的变化模式(包括继承、包括派生、包括限制、包括组合等),最终 Zero权限框架中合计支持64种Profile配置,如此就解决了资源 能不能 访问的问题。

3.7.1.3.N维安全视图(View)

前文解决了资源 能不能 访问的问题,本章就在可访问的基础上解决 访问多少 的问题,Zero权限框架中的 S_RESOURCES_ACTION 是强绑定关系,它们之间只会单纯对比操作级别和资源需求级别是否可访问,一旦访问成功,就会衍生计算读写操作的边界,在Zero权限框架中读写边界的划定取决于安全视图 S_VIEW 中的定义。

安全视图基础

安全视图的基础维度如下:

字段名 含义 取值

NAME

视图名称

默认取值 DEFAULT。

POSITION

视图位置

默认取值 DEFAULT。

OWNER_TYPE

视图所属者类型

只包含两种:ROLE-角色视图,USER-用户视图。

OWNER

视图所属者ID

如果是角色视图则是角色ID,如果是用户视图则是用户ID。

RESOURCE_ID

视图所属资源

当前视图关联的 S_RESOURCE 资源ID,一个资源可能存在多个安全视图。

POSITION 和 NAME 构造的视图的核心维度,在系统出现不同需求时会起重要作用:

场景 NAME POSITION

单模块无视图管理

DEFAULT

DEFAULT

单模块带视图

?

DEFAULT

多模块无视图管理

DEFAULT

?

多模块多视图管理

?

?

此处解释一下模块的概念,此处的 模块 并非我们开发过程中的模块,此处的模块底层关联模型只有一个,而模块更多是从列表作为入口。例如:

  • 单纯的CRUD应用(角色管理),管理过程中它的模块只有一个,从角色列表进入,然后管理,一般场景不会开第二模块进行特殊管理。

  • 带分类的CRUD应用(订单管理),可能带有不同列表管理处理,如正在执行的订单模块、已经完成的订单模块,而此时后台关联的模型依旧是 订单,这种情况下 POSITION 就显得很重要。

而且 POSITION 会比资源多一个维度,通常资源是后接口绑定,如 /api/xxx/search 的资源接口,但这个资源接口由于支持查询引擎语法,可能应用于不同的菜单入口(上述提到的正在执行的订单、已完成的订单)等,这种情况下两个菜单共享了一个资源,而为了针对不同的菜单定义 角色视图/用户视图,最好的方式就是启用 POSITION 参数。如此计算下来,POSITION既不和查询条件绑定(不同页面、不同位置、同一查询条件),也不可以和页面绑定,如果出现 TAB 页签会造成同一个页面中出现两种不同的查询(可能是两种不同的 POSITION),最终它只能和列表的配置绑定,直接在前端中提供它的配置来完成和列表绑定的过程,这一块的用法属于 Zero权限框架中的难点,其应用范围十分广泛,现阶段通常使用场景如下:

  • 按类型划分位置信息:分类字段管理 /ambient/tabular/:type 不同页面取不同的 POSITION,实现抽象态的列表管理,这种思路同样适用于:档案、合同、项目、员工、客户、分类等。

  • 按类型划分位置信息:如待办列表和已办列表,最终访问资源可能都是 /api/todo/search,而由于状态不同,所以设置不同的 POSITION 实现视图的定制。

  • 按流程划分QBE:目前系统中流程右上角的QBE列表页是基于此种逻辑,几乎不使用开发的模式就定制完成。

参考下图的结构:

zero p view

上图结构可以看到 POSITIONNAME(在模块访问中通常使用 VIEW)的使用场景会有所差异:

  • POSITION主要用于模块维度的拓展,它的起点是模块。

  • VIEW主要用于视图拥有者维度的拓展,它的起点是拥有者,如角色、用户、目录级(实验版本)。

安全视图类

Zero中存在一个特殊的参数对象:

    public class Vis extends JsonObject

    // 该参数对象使用时可如下:
    @POST
    @Path("/{actor}/search")
    @Address(Addr.Post.SEARCH)
    @Adjust(Orders.MODULE)
    JsonObject search(@PathParam("actor") String actor,
                      @BodyParam JsonObject data,
                      @QueryParam(KName.MODULE) String module,
                      @PointParam(KName.VIEW) Vis view);

该参数的格式比较特殊,通常使用的是 [view,position] 的数据格式,也是此处的 @PointParam 注解解析的内容,它可以将上述格式直接解析成视图的两个核心维度( NAME, POSITION ),并将该维度应用于任意支持它的接口。Vis类中存在一个特殊方法smart会对视图数据格式做智能解析,它支持的几种格式如下:

  • Vis类型:如果传入的类型是Vis类型,则直接做引用赋值。

  • JsonObject类型:如果传入的类型是JsonObject类型,则解析格式:{"position": "xxx","view":"xxx"}

  • JsonArray类型:如果传如的类型是JsonArray类型,则解析格式:`[view,position]`执行解析。

  • String类型:如果传如类型是String类型,除了完成URL的 decode 流程之外:

    • 如果String类型是JsonArray格式则做一次强制转换,执行JsonObject类型解析。

    • 如果String类型是JsonArray格式则做一次强制转换,执行JsonArray类型解析。

    • 否则String类型参数直接作为视图名称看待,而赋 POSITION 为默认值 DEFAULT

  • 默认创建专用默认视图:view = DEFAULT, position = DEFAULT

窗口定义

安全视图的窗口定义主要依靠下边几个字段:

字段名 含义

PROJECTION

JsonArray格式,执行该视图的列过滤,直接过滤掉接口返回数据的列信息。

CRITERIA

JsonObject格式,执行该视图默认的 Qr 语法注入,启用查询引擎追加接口的查询条件语法。

ROWS

JsonObject格式,针对行数据执行筛选,生成 IN 语句筛选特定行,通常是查询引擎无法做细粒度筛选时的一种折中选择。

VISITANT

布尔值,是否启用 虚拟视图(资源访问者)

  • PROJECTION 会作用于不同类型的前端组件,通常用于 LIST/FORM 两种,Zero框架中的保存列表的列信息以及表单中针对部分表单执行字段过滤就依赖它来完成,它是后置过滤(实际会从数据库中查询出所有信息进行值提取,现阶段没有明显的性能问题)。

  • CRITERIA 主要针对于查询,它会隐式修改查询引擎的 Qr 语法,导致前端发送查询条件在安全视图作用下被直接修改,如果用户中出现了多个角色、多个用户组,则按照最终资源需求中定义的 Profile 来完成查询条件的拼合,默认模式下多个角色之间使用 OR 连接符。

  • ROWS 针对特殊资源提取,提供基于主键的直接命中条件,解决异构查询模式下用户无法使用Join的情况,由于表单是单条数据记录,所以一般表单接口无法支持该属性(设置了也没有效果);通常此属性作用于列表:

    • DATA:在数据层面,列表处理过程中直接针对条件执行过滤,典型应用为:菜单筛选、字典筛选、分类树筛选。

    • META:元数据层面,处理过程中只读取ROWS中设置过的的信息(特殊模式下载界面呈现模式出现ReadOnly时,它的定义位于UI配置中,而不是安全视图层。

虚拟视图(资源访问者)部分参考下一个章节的详细说明,上述限制中,虽然 ROWS 无法直接作用于表单属性级的过滤窗口操作,但是它可以实现动态表单(/api/ui/form)模式下的属性集过滤,比如读取表单的属性有25个,使用 `ROWS`直接过滤掉一部分留下一部分,最终输出的是配置、配置、配置,最终表单引擎根据配置渲染表单,可以完成间接作用流程。

视图检索流程

看完了上述安全视图的方方面面之后,视图检索流程就变得很简单了(后端会根据访问资源键值生成 session-<METHOD>:<URI>:<POSITION>/<VIEW> 格式的视图缓存键)。下边是用户访问某个资源接口时的详细流程:

  1. 用户发送请求到某个资源接口如:/api/xxx/resource

  2. 系统检索该资源是否存在用户级的 S_VIEW 记录(OWNER_TYPE = USER, OWNER = <USER_ID>),如果存在该记录,则直接提取安全视图记录对资源执行前后(BEFORE/AFTER)计算。

    • BEFORE计算:BEFORE计算的核心算法主要在于修改参数,它的性能更高,一般直接作用于 criteria 参数部分实现查询条件的注入流程。

    • AFTER计算:AFTER计算会完整访问数据库,在查询出来的结果集中做运算,虽然性能会有损耗,但在某些场景下(需要全量元数据)是必须要走AFTER的。

  3. 若不存在用户级的 S_VIEW 记录,则继续检索是否有角色级的 S_VIEW 记录,若存在则计算。

  4. 上述两步都不存在时,忽略安全视图,可访问资源内所有内容。

从上述流程可以知道,用户级安全视图优先级比角色高,一般用户级安全视图都是个人视图模式存在,比如某个模块的视图管理,而角色级的视图都是管理员预设,单个用户不可以更改,比如管理员直接针对财务人员以外的角色设置不可访问某些资源的固定列如薪资、账期等。

最终 访问多少 的问题就直接被安全视图处理掉了,不同角色不同用户在此框架之下访问同一个接口时返回数据就可能出现不同,那么这样就解决了资源重用并且 访问多少 的问题。 :data-uri:

3.7.1.4.资源访问者(Visitor)

多用于抽象层次比较高的 动态建模 领域的权限控制。

本章进入Zero权限框架中的一个新的领域:虚拟资源/资源访问者,在讲虚拟资源之前先思考:为什么要使用虚拟资源?前文安全视图中的定义不知道读者是否发现一个小问题:静态的——一旦绑定了资源之后,就只能在某个资源中直接设置参数和条件,而这里设置的所有条件以及参数都 不依赖输入,您考虑下边一个场景。

我在后端书写了一个接口:/api/xxx/:type,这个接口在后端的定义的接口和 S_RESOURCE 记录仅有一条(为什么,除非您直接愿意写成 /api/xxx/type1/api/xxx/type2 两个接口),这种场景下,意味着如果`type`有三个值,那么我所期望的安全视图应该有三种,根据前文提到的,您可以设置 S_VIEWPOSITION 来限定资源视图,就完成了三种模式下的定义。但若现在我的 :type 参数不是三种,可能存在N种或者上百种,如何解决?Zero为了解决这种安全视图方案,提供了 资源访问者 的概念。资源访问者存储于后端配置表 S_VISITANT 中,一个 S_VIEW(严格说是 VISITANT = true 的视图记录)可能包含无数个资源访问者。

zero p visit arch

从上图可以知道在动态建模过程中,路由器防火墙 可能意味着不同模型,而且应用程序会不断添加新的设备类型,产生新的模型,这种模式下使用 POSITION 扩展会造成大量冗余,况且此时的入口是虚拟资源,即意味着:您在访问该资源时,您是不知道您访问的资源究竟是路由器还是防火墙,那么这样的流程中,就只能通过 访问者 语法计算出真实访问者,然后根据资源访问者去定位真实的资源。从这点意义上讲您可以理解两点:

  • POSITION:先知模式,在访问资源之前,您已经知道您要访问的维度数据是什么,资源访问入口是具象层。

  • VISITANT:后知模式,在访问资源之前,您不知道您要访问的维度数据是什么,资源访问入口是抽象层(这也是虚拟资源一词的来源)。

Zero中按照如下流程配置一个资源访问者:

  1. 资源本身(S_RESOURCE)将该资源定义成一个虚拟资源(VIRTUAL = true)。

  2. 在(S_RESOURCE)资源字段中定义访问者基本规则:

    • 设置访问者语法 SEEK_SYNTAX 字段。

    • 设置访问者配置 SEEK_CONFIG 字段。

    • 设置访问者组件 SEEK_COMPONENT 字段(Java类名)。

  3. 用户发送请求过来时会读取 S_VIEW 的视图信息,一旦读取到视图信息后,对 VISITANT = true执行校验,校验成功之后执行资源访问者流程。

资源访问者流程可以总结成两个大步骤:

步骤 说明

真实资源查找

根据 S_RESOURCE 中的 VIRTUAL = true 的定义去查找真实资源,真实资源的查找就借用访问者配置(前文提到的基本规则)来实现。

访问者安全视图

工具 S_VIEW 中的 VISITANT = true 的定义去同步查找真实资源模式下的安全视图,该视图比 S_VIEW 中扩展的属性更多,渗透到表单级、操作级、非接口级,数据更强大的ACL控制视图逻辑。

访问者逻辑

资源访问者的内部逻辑流程如下:

  1. 检查访问视图 S_VIEW 是否一个带有访问者的安全视图(VISITANT = true)的定义。

  2. 根据资源 S_RESOURCE 中的访问者定义(seekSyntax / seekConfig / seekComponent)计算真实资源访问规则。

  3. 扫描资源访问者的 模式(Replace/Extend)和 作用阶段(EAGER/DELAY),并执行访问者操作。

  4. 读取访问者相关信息,将这些信息和 S_VIEW 中的信息合并计算,计算访问者安全窗口。

关于访问者语法结构定义在此多做点说明,在实际场景中,通常资源的抽象模式(访问者维度)都只有一个维度,所以访问者语法也只是针对资源的访问做一个维度层面的拓展,若您的应用中真的出现了 超级接口,访问者维度需要通过多维模式去实现时,您可以自定义扩展:

  • 单维度标准化:`seekSyntax`定义可完成。

  • 多维度标准化:`seekSyntax`新版多维访问者定义完成。

  • 多维度扩展:`seekConfig/seekComponent`自定义完成。

个人不推荐在系统中做过多的 超级接口 ——一个接口完成多种不同的逻辑,这样的方式运维将会造成一定的压力,并且不容易拓展,但在动态建模和动态接口部分,往往会牵涉到模型的变体,变体出现时这种模式的维度是必须存在的,所以就只能依赖扩展配置来完成。

多说一句:Zero扩展框架中存在很多 config/component 的架构,通常 component 是一个实现了固定接口的Java类,而 config 则是和该类配套的配置数据(Json格式),这样的格式可以让任何开发人员自由发挥拓展自己的应用,访问者逻辑部分也是如此。

访问者语法 存在的目的是查找视图中对应的访问者信息,由于一个视图可能存在多个访问者,所以系统必须保证本次请求的访问者信息——要么只有1个,要么不存在;否则系统会出现二义性问题导致最终无法定位使用哪个资源访问者来处理请求,所以目前Zero权限框架的版本中,访问者主键 S_VISITANT 表中的 SEEK_KEY 字段是唯一的,而访问者语法的最终目的就是计算 SEEK_KEY 生成访问者查询条件。

(执行维度)模式和阶段

资源访问者语法中的模式 mode 信息( S_VISITANT 表中的 MODE 字段):

  • Replace:替换模式,这种模式下,访问者视图会直接覆盖 S_VIEW 中的安全窗口规则,也就是说资源访问不再遵循 S_VIEW 中的安全规则,而直接使用访问者规则。

  • Extend:扩展模式,这种模式下,访问者视图会和 S_VIEW 中的安全窗口规则合并计算,形成新的组合好的访问者规则。

它的作用如下:

zero p visit mode

资源访问者语法中的阶段 phase 信息( S_VISITANT 表中的 PHASE 字段):

  • EAGER:通常当前资源立即生效,一般执行数据读取时会使用 EAGER 阶段(就在当前接口生效)。

  • DELAY:这种阶段通常是读取配置项作用于子资源或其他资源时生效,一般读取元数据和配置数据时使用 DELAY 阶段(DELAY阶段 DataRegion 中的视图模式依旧生效)。

它的作用如下:

zero p visit phase

对于直接开发的接口,基本上EAGER模式就可以满足大量的接口安全控制需求,您不需要开发额外的逻辑就实现了安全视图的控制,但对于比较特殊的基于配置的流程中,通常接口会分为:元数据接口和数据接口两部分,二者相互影响并相互作用,这样的条件下,资源访问者就体现出它的价值了,一个访问者就解决了元数据接口和数据接口的双重安全作用,而不需要依赖每个位置都定义对应的接口。

(定义维度)类型/标识/唯一键

访问者记录中虽然保存了 SEEK_KEY,但在不同的业务场景中,它无法做 全局标识,所以根据实际需求,此处设计在后期做过一些基本改动,访问者标识维度如下:

字段 含义

TYPE

访问者类型,针对资源维度的分类定义,现阶段支持:FORM、LIST、OP、VIEW 四种,服务于 zero-atom 动态建模。

IDENTIFIER

模型标识符,针对模型维度的分类定义,主要提供master模型的基础访问者(限定于所有场景)。

SEEK_KEY

访问者主键,系统可以根据访问者主键查询访问者信息。

访问者标识维度从执行和定义两个方向处理:

  1. 定义维度:VIEW_ID, TYPE, IDENTIFIER 形成唯一键。

  2. 执行维度:VIEW_ID, TYPE, SEEK_KEY 形成唯一键。

举个例子,在读取表单配置时,表单的配置可直接使用:`VIEW_ID,TYPE,SEEK_KEY`限定:

  • VIEW_ID :标识了读取表单的资源接口信息。

  • TYPE :手动定义,静态模式下使用固定值,动态模式中则可以直接使用限定值。

  • SEEK_KEY :根据表单计算这种类型的主键,此时它的值可以是表单的ID(动态),也可以是表单的CODE(静态)。

这样处理之后就实现了表单资源的唯一访问者读取。

SEEK_KEY 目前最常用的两种场景如:

  1. 动态建模过程中,资源访问会牵涉 controlId(表单、列表的组件ID),它的格式通常如下:

    {
        "type": "LIST / FORM / OP",
        "controlId": "UI_CONTROL表中定义的组件的ID,由于UI_CONTROL中已经定义了模型标识符,所以此处模型标识符则可直接省略。"
    }
  2. 静态建模过程中,资源访问者会牵涉到其他内容来构造 SEEK_KEY,如:

    {
        "type": "LIST / FORM /OP",
        "workflow": "工作流名称"
    }

现在版本中的流程 SEEK_KEY 的值格式通常是::workflow/:event/DEFAULT ,其中包含了流程名称和任务名称,这样就可以保证流程中的每个节点都可设置访问者,配合 TYPE 字段实现列表、表单、操作不同级别的访问。

访问控制

访问者对列表的控制基本和 S_VIEW 同源,主要覆盖如下:

字段 含义

DM_ROW

等价于视图中的 ROWS 限定规则,前端标记:H - Horizon,水平限定。

DM_QR

等价于视图中的 CRITERIA 限定规则,前端标记:Q - Query,查询限定。

DM_COLUMN

等价于视图中的 PROJECTION 限定规则,前端标记:V - Vertical,垂直限定。

访问者优于视图的地方在于它还提供了表单级的控制,主要覆盖如下:

字段 关键字 含义

ACL_VISIBLE

可见性

可见属性集设置,限定表单中的某些表单字段是否可见。

ACL_VIEW

只读

只读属性集设置,可编辑依靠计算:可见性 - 只读

*ACL_VARIETY

多样性

多样性属性集设置,用于控制集合类型的属性变体,如数组类的多样性属性集,递归三种属性集,标记某个子属性配置。

ACL_VOW

引用

针对引用类型的属性进行限定,比如订单中关联了员工信息,而员工信息可直接被订单接口的访问者执行表单级属性过滤。

ACL_VERGE

依赖

保存了所有依赖属性的相关信息,和引用方向相反。

上述属性中 ACL_VARIETY 属于特殊访问属性,通常可针对列表、集合等不同的访问属性进行内部数据结构的限定,有了这些限定之后,不同的用户在访问同一张表单可达到如下权限控制效果:

  • 访问的表单长相不同(可见性处理)。

  • 访问同样的表单部分属性看见的内容不同,包括只读、可编辑。

  • 表单引入:有值不可看的情况,这种情况下表单中会显示 ** 来处理(仅针对特殊角色和用户生效)。

  • 依赖属性的不可见处理,所有和表单关联的数据出现不可看的情况。

3.7.1.5.配置步骤

到这里,所有和Zero权限框架相关的内容就已经讲完了,本章节主要讲解配置步骤,开发人员可参考此章节配置上述所有内容。

1. 权限基础配置

权限基础配置在于配置用户是否有权限访问某个资源。

  1. 根据:S_USER / S_ROLE / S_GROUP / S_PERMISSION 设置账号到权限的路径数据信息。

  2. 开发自定义接口如:/api/xxx/order,并且将此资源接口信息录入到 S_RESOURCE 表和 S_ACTION 表中,并将 S_ACTION 记录挂在某个 S_PERMISSION 权限之下。

    • S_RESOURCE 中针对Profile进行资源需求配置:MODE_ROLE / MODE_GROUP / MODE_TREE,确保用户最终计算出来的权限集在对应的Profile之中(参考:仅配置 MODE_ROLE = UNION)。

    • S_ACTION 中配置的 LEVEL 一定要大于 S_RESOURCE 中定义的操作级别。

  3. 将上述配置通过 Loader 导入系统中,重启容器生效(后续使用管理端则不需要重启)。

操作级别的内部定义:

符号 含义

0

READONLY

只读级别,最小等级。

1

READ

标准读取,通常是单记录读取。

2

READ_INTEGRATION

集成读取,通常会开放接口读取。

3

READ_EXPORT

从数据库中批量导出时所需。

4

ADD

创建和批量创建级别。

5

ADD_IMPORT

导入专用级别。

6

ADD_INTEGRATION

集成创建,通常会开放接口创建。

7

ADD_META

元数据创建接口,创建配置专用。

8

EDIT_APPROVE

审批确认更新接口,部分字段更新。

9

EDIT

标准编辑,更新和批量更新级别。

10

EDIT_INTEGRATION

集成更新,通常开放接口实现更新逻辑。

11

EDIT_META

元数据更新接口,更新配置专用。

12

DELETE

标准删除,删除和批量删除级别。

13

DELETE_PURGE

清除专用,通常用于数据清空。

14

DELETE_META

元数据删除专用,删除配置专用。

15

FULL

最高操作级别。

2. 视图配置

一般静态视图配置都是配置角色级别的视图相关信息,通常不会配置用户级视图。

  1. 找到权限基础配置中 S_RESOURCE 的主键,填充到 S_VIEW 中的 RESOURCE_ID 字段中。

  2. 没有特殊说明 NAMEPOSITION 都可以直接配置成 DEFAULT 默认值。

  3. OWNER_TYPE 中配置 ROLE,然后找到登录账号对应的角色ID,填充到 OWNER 中。

  4. 配置视图的三个核心维度:ROWS, PROJECTION, CRITERIA

  5. 将上述配置的 S_VIEW 记录导入到系统中,重启容器生效(后续使用管理端则不需要重启)。

3. 访问者配置

如果牵涉到访问者配置,则遵循如下流程执行:

  1. 将资源定义 S_RESOURCE 中的资源设置成 虚拟资源VIRTUAL = true)。

  2. 为虚拟资源配置 访问者语法,两种配置模式:

    • 直接配置 SEEK_SYNTAX 字段生成标准化的访问者语法模块。

    • 配置 SEEK_CONFIG / SEEK_COMPONENT 字段生成扩展的访问者语法模块。

  3. 配置好之后在根据所需要为资源配置访问者信息:S_VISITANT 表中追加相关记录。

3.7.1.6.示例/格式
S_VIEW 中的 PROJECTION

S_VIEW 表结构中的 PROJECTION 通常是 JsonArray 结构,如:

[
    "key",
    "name",
    "code",
    "createdAt",
    "createdBy"
]

上述配置会包含两个含义:

  • 在读取资源过程中使用了该视图之后,只会读取 五列 信息。

  • 读取的 五列 会按照配置顺序读取,即列表中的列顺序为:key, name, code, createdAt, createdBy

S_VIEW 中的 CRITERIA

S_VIEW 表结构中的 CRITERIA 通常是 JsonObject 结构,直接追加查询引擎语法,最终条件和请求条件按 AND 操作符合并。

S_VIEW 中的 ROWS

S_ROWS 表结构中的 ROWS 是一个 JsonObject 结构,会生成 IN 查询条件,如:

{
    "name" : [ "zero.desktop", "zero.desktop.my", "zero.desktop.my.todo-pending"],
    "code" : [ "A", "B" ]
}

您可以将上述配置片段理解成 QR 查询引擎的片段语法,如上述代码中如果 name, code 对应字段为 NAME, CODE,则会生成查询条件:

WHERE NAME IN ('zero.destkop', 'zero.desktop.my', 'zero.desktop.my.todo-pending') OR CODE IN ('A', 'B')

根据 QR 查询引擎规范,您可以按下边配置将中间连接符配置成 AND

{
    "name": ["..."],
    "code": ["..."],
    "": true
}
S_RESOURCE 中的 SEEK_SYNTAX

SEEK_SYNTAX 通常格式如下:

{
    "phase": "AFTER",
    "data": {
        "type": "RECORD",
        "viewId": "`${viewId}`",
        "identifier": "psi.pos"
    }
}

上述代码是一个单维度访问者代码,data`节点会包含一个 `type 属性,它和 phase 会构成不同的值处理模式,此处若您的数据来自于输入数据,则可使用 "`" 符号执行 JEXL 转换,如上述数据就会根据 type, viewId, identifier 计算访问者的 SEEK_KEY 来提取访问者信息。

上述配置中的 phasedata 节点中的 type 最终会生成如下格式的合法值:

phase type 含义

BEFORE_PROJECTION

BEFORE

PROJECTION

前置操作,修改查询引擎参数 projection。

BEFORE_CRITERIA

BEFORE

CRITERIA

前置操作,修改IQ讯引擎参数 criteria。

AFTER_RECORD

AFTER

RECORD

后置操作,执行记录处理,单数据增删改的记录过滤访问者计算。

AFTER_ROWS

AFTER

ROWS

后置操作,多记录,执行行筛选,筛选出集合数据中的某些行数据访问者计算。

AFTER_COLLECTION

AFTER

COLLECTION

后置操作,多记录,执行列筛选,过滤部分属性。

SEEK_SYNTAX 的多维格式如下:

{
    "phase": "AFTER",
    "selector": "io.vertx.tp.optic.secure.ConfineKind",
    "kind": "type",
    "data": {
        "ATOM": "`${identifier}/${control}`",
        "FLOW": "`${workflow}/${node}/DEFAULT`"
    }
}

上述代码段中,访问者调用中会使用 io.vertx.tp.optic.secure.ConfineKind 完成访问者选择,选择过程根据输入参数 type 值执行计算,由于使用了组件,所以执行过程可忽略 data 节点的数据信息,最终:

  • type = ATOM 会生成访问者的 SEEK_KEY = <模型标识符>/<控件ID>,动态建模可用。

  • type = FLOW 会生成访问者的 SEEK_KEY = <工作流名称>/<节点名称>/DEFAULT,流程引擎专用。

您也可以定义自己的 Confine 接口组件配置 selector 完成多维数据访问者扩展。Confine接口的定义如下:

public interface Confine {
    Future<JsonObject> restrict(JsonObject request, JsonObject syntax);
}

其中此处的 syntax 就是 SEEK_SYNTAX 配置的内容,而 request 参数对应到前文中 data 节点可使用的预设参数(预设参数不包含您在 Http 请求体 Body 中传入的参数),预设参数如下:

参数名 默认值 含义

appId

多应用模式中,所属应用程序ID,来自请求头:X-App-Id

appKey

所属应用程序的Key,敏感数据访问专用,来自请求头:X-App-Key

sigma

统一标识符,来自请求头:X-Sigma

language

多语言模式中,当前应用的语言信息,来自请求头:X-Lang

tenantId

多租户模式中,所属租户的ID,来自请求头:X-Tenant-Id

resourceId

当前请求正在访问的资源信息。

viewId

当前资源访问者所属视图ID。

view

DEFAULT

当前资源访问者访问的视图名称,默认 DEFAULT

position

DEFAULT

当前资源访问者访问的视图位置,默认 DEFAULT

S_VISITANT 中的 ACL_

由于访问者表中的 DM_ 字段格式和 S_VIEW 中保持一致,此处不再重复讲解。

  • DM_ROW 对应 ROWS

  • DM_QR 对应 CRITERIA

  • DM_COLUMN 对应 PROJECTION

最后简单讲解下 ACL_ 表单级语法:

字段 类型 格式和含义

ACL_VERGE

JsonObject

一般格式是:field = JsonObject 结构,包含依赖字段名和依赖字段相关配置。

ACL_VISIBLE

JsonArray

直接是 [field1, field2, …​] 结构,包含了可见性字段集,最终会转换成 Set。

ACL_VIEW

JsonArray

直接 [field1, field2, …​] 结构,包含了只读字段集,最终会转换成 Set。

ACL_VARIETY

JsonObject

Json格式,用于构造 AclView/AclMap专用,执行类型为 DATA。

ACL_VOW

JsonObject

Json格式,用于构造 AclView/AclMap专用,执行类型为 REFERENCE。

最后谈谈响应格式中的的 __acl 字段,这是Zero标准数据规范中的一部分,如果某个接口(包括JsonArray返回的接口)中包含了 __acl 则证明该接口包含ACL控制信息,它的格式如下:

{
    "access": [],
    "edition": [],
    "fields": []
}

上述格式是初期版本格式,代表:

  • fields:当前表单、列表能访问的所有属性集合。

  • access:您可以访问的所有属性集合。

  • edition:您可以编辑的所有属性集合。

3.7.2.管理端

前文讨论了Zero权限框架中的 消费端,本章节开始讨论权限框架的 管理端,管理端的主要目的是为您定制所需要的核心配置数据,并且通过交互式界面直接为用户执行权限、视图、访问者的授权工作,管理端入口在Zero Extension框架中有三个:

  • 角色管理 → 权限设置

  • 权限设置 → 角色授权 → 选择某个角色

  • 权限设置 → 用户特权(现阶段版本还未放出来)

管理端的主体是 角色,所以管理端的所有操作都是角色级的,只是在设计过程中管理端遵循如下设计原则:

3.8.动态建模(zero-atom)

3.8.接口/任务配置(zero-jet)

3.10.工作流配置(zero-wf)

3.11.集成服务配置(zero-is)

3.12.模块化配置(zero-berrery)